diff --git a/compiler/rustc_abi/src/callconv.rs b/compiler/rustc_abi/src/callconv.rs index 9fb70b80c9ef..4529ab8058e9 100644 --- a/compiler/rustc_abi/src/callconv.rs +++ b/compiler/rustc_abi/src/callconv.rs @@ -65,8 +65,6 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { Ty: TyAbiInterface<'a, C> + Copy, { match self.backend_repr { - BackendRepr::Uninhabited => Err(Heterogeneous), - // The primitive for this algorithm. BackendRepr::Scalar(scalar) => { let kind = match scalar.primitive() { diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 45cd0b517f6c..53243266f992 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -130,6 +130,7 @@ impl LayoutCalculator { }, backend_repr: BackendRepr::ScalarPair(a, b), largest_niche, + uninhabited: false, align, size, max_repr_align: None, @@ -221,8 +222,9 @@ impl LayoutCalculator { LayoutData { variants: Variants::Empty, fields: FieldsShape::Primitive, - backend_repr: BackendRepr::Uninhabited, + backend_repr: BackendRepr::Memory { sized: true }, largest_niche: None, + uninhabited: true, align: dl.i8_align, size: Size::ZERO, max_repr_align: None, @@ -400,6 +402,7 @@ impl LayoutCalculator { fields: FieldsShape::Union(union_field_count), backend_repr: abi, largest_niche: None, + uninhabited: false, align, size: size.align_to(align.abi), max_repr_align, @@ -447,7 +450,6 @@ impl LayoutCalculator { Scalar::Union { .. } => {} }; match &mut st.backend_repr { - BackendRepr::Uninhabited => {} BackendRepr::Scalar(scalar) => hide_niches(scalar), BackendRepr::ScalarPair(a, b) => { hide_niches(a); @@ -639,9 +641,8 @@ impl LayoutCalculator { let same_size = size == variant_layouts[largest_variant_index].size; let same_align = align == variant_layouts[largest_variant_index].align; - let abi = if variant_layouts.iter().all(|v| v.is_uninhabited()) { - BackendRepr::Uninhabited - } else if same_size && same_align && others_zst { + let uninhabited = variant_layouts.iter().all(|v| v.is_uninhabited()); + let abi = if same_size && same_align && others_zst { match variant_layouts[largest_variant_index].backend_repr { // When the total alignment and size match, we can use the // same ABI as the scalar variant with the reserved niche. @@ -683,6 +684,7 @@ impl LayoutCalculator { }, backend_repr: abi, largest_niche, + uninhabited, size, align, max_repr_align, @@ -853,9 +855,8 @@ impl LayoutCalculator { }; let mut abi = BackendRepr::Memory { sized: true }; - if layout_variants.iter().all(|v| v.is_uninhabited()) { - abi = BackendRepr::Uninhabited; - } else if tag.size(dl) == size { + let uninhabited = layout_variants.iter().all(|v| v.is_uninhabited()); + if tag.size(dl) == size { // Make sure we only use scalar layout when the enum is entirely its // own tag (i.e. it has no padding nor any non-ZST variant fields). abi = BackendRepr::Scalar(tag); @@ -995,6 +996,7 @@ impl LayoutCalculator { memory_index: [0].into(), }, largest_niche, + uninhabited, backend_repr: abi, align, size, @@ -1355,9 +1357,7 @@ impl LayoutCalculator { _ => {} } } - if fields.iter().any(|f| f.is_uninhabited()) { - abi = BackendRepr::Uninhabited; - } + let uninhabited = fields.iter().any(|f| f.is_uninhabited()); let unadjusted_abi_align = if repr.transparent() { match layout_of_single_non_zst_field { @@ -1378,6 +1378,7 @@ impl LayoutCalculator { fields: FieldsShape::Arbitrary { offsets, memory_index }, backend_repr: abi, largest_niche, + uninhabited, align, size, max_repr_align, diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index dbb4bed5cdd9..098638b6bcfa 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1404,7 +1404,6 @@ impl AddressSpace { #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature = "nightly", derive(HashStable_Generic))] pub enum BackendRepr { - Uninhabited, Scalar(Scalar), ScalarPair(Scalar, Scalar), Vector { @@ -1423,10 +1422,9 @@ impl BackendRepr { #[inline] pub fn is_unsized(&self) -> bool { match *self { - BackendRepr::Uninhabited - | BackendRepr::Scalar(_) - | BackendRepr::ScalarPair(..) - | BackendRepr::Vector { .. } => false, + BackendRepr::Scalar(_) | BackendRepr::ScalarPair(..) | BackendRepr::Vector { .. } => { + false + } BackendRepr::Memory { sized } => !sized, } } @@ -1445,12 +1443,6 @@ impl BackendRepr { } } - /// Returns `true` if this is an uninhabited type - #[inline] - pub fn is_uninhabited(&self) -> bool { - matches!(*self, BackendRepr::Uninhabited) - } - /// Returns `true` if this is a scalar type #[inline] pub fn is_scalar(&self) -> bool { @@ -1471,7 +1463,7 @@ impl BackendRepr { BackendRepr::Vector { element, count } => { cx.data_layout().vector_align(element.size(cx) * count) } - BackendRepr::Uninhabited | BackendRepr::Memory { .. } => return None, + BackendRepr::Memory { .. } => return None, }) } @@ -1492,7 +1484,7 @@ impl BackendRepr { // to make the size a multiple of align (e.g. for vectors of size 3). (element.size(cx) * count).align_to(self.inherent_align(cx)?.abi) } - BackendRepr::Uninhabited | BackendRepr::Memory { .. } => return None, + BackendRepr::Memory { .. } => return None, }) } @@ -1506,9 +1498,7 @@ impl BackendRepr { BackendRepr::Vector { element, count } => { BackendRepr::Vector { element: element.to_union(), count } } - BackendRepr::Uninhabited | BackendRepr::Memory { .. } => { - BackendRepr::Memory { sized: true } - } + BackendRepr::Memory { .. } => BackendRepr::Memory { sized: true }, } } @@ -1704,6 +1694,11 @@ pub struct LayoutData { /// The leaf scalar with the largest number of invalid values /// (i.e. outside of its `valid_range`), if it exists. pub largest_niche: Option, + /// Is this type known to be uninhabted? + /// + /// This is separate from BackendRepr because uninhabited return types can affect ABI, + /// especially in the case of by-pointer struct returns, which allocate stack even when unused. + pub uninhabited: bool, pub align: AbiAndPrefAlign, pub size: Size, @@ -1735,14 +1730,14 @@ impl LayoutData { /// Returns `true` if this is an aggregate type (including a ScalarPair!) pub fn is_aggregate(&self) -> bool { match self.backend_repr { - BackendRepr::Uninhabited | BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => false, + BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => false, BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => true, } } /// Returns `true` if this is an uninhabited type pub fn is_uninhabited(&self) -> bool { - self.backend_repr.is_uninhabited() + self.uninhabited } pub fn scalar(cx: &C, scalar: Scalar) -> Self { @@ -1778,6 +1773,7 @@ impl LayoutData { fields: FieldsShape::Primitive, backend_repr: BackendRepr::Scalar(scalar), largest_niche, + uninhabited: false, size, align, max_repr_align: None, @@ -1802,6 +1798,7 @@ where backend_repr, fields, largest_niche, + uninhabited, variants, max_repr_align, unadjusted_abi_align, @@ -1813,6 +1810,7 @@ where .field("abi", backend_repr) .field("fields", fields) .field("largest_niche", largest_niche) + .field("uninhabited", uninhabited) .field("variants", variants) .field("max_repr_align", max_repr_align) .field("unadjusted_abi_align", unadjusted_abi_align) @@ -1877,7 +1875,6 @@ impl LayoutData { BackendRepr::Scalar(_) | BackendRepr::ScalarPair(..) | BackendRepr::Vector { .. } => { false } - BackendRepr::Uninhabited => self.size.bytes() == 0, BackendRepr::Memory { sized } => sized && self.size.bytes() == 0, } } diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs index a9b8e1bd3935..1b3f86c8405d 100644 --- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs +++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs @@ -638,9 +638,7 @@ impl<'tcx> CPlace<'tcx> { } CPlaceInner::Addr(_, Some(_)) => bug!("Can't write value to unsized place {:?}", self), CPlaceInner::Addr(to_ptr, None) => { - if dst_layout.size == Size::ZERO - || dst_layout.backend_repr == BackendRepr::Uninhabited - { + if dst_layout.size == Size::ZERO { return; } diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index a1123fafe2f3..b3b7f35af8cf 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -310,7 +310,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc let layout = self.layout_of(tp_ty).layout; let _use_integer_compare = match layout.backend_repr() { Scalar(_) | ScalarPair(_, _) => true, - Uninhabited | Vector { .. } => false, + Vector { .. } => false, Memory { .. } => { // For rusty ABIs, small aggregates are actually passed // as `RegKind::Integer` (see `FnAbi::adjust_for_abi`), diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs index 8b8b54753e7f..bac4fc51300a 100644 --- a/compiler/rustc_codegen_gcc/src/type_of.rs +++ b/compiler/rustc_codegen_gcc/src/type_of.rs @@ -84,7 +84,7 @@ fn uncached_gcc_type<'gcc, 'tcx>( false, ); } - BackendRepr::Uninhabited | BackendRepr::Memory { .. } => {} + BackendRepr::Memory { .. } => {} } let name = match *layout.ty.kind() { @@ -179,19 +179,16 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { fn is_gcc_immediate(&self) -> bool { match self.backend_repr { BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => true, - BackendRepr::ScalarPair(..) | BackendRepr::Uninhabited | BackendRepr::Memory { .. } => { - false - } + BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => false, } } fn is_gcc_scalar_pair(&self) -> bool { match self.backend_repr { BackendRepr::ScalarPair(..) => true, - BackendRepr::Uninhabited - | BackendRepr::Scalar(_) - | BackendRepr::Vector { .. } - | BackendRepr::Memory { .. } => false, + BackendRepr::Scalar(_) | BackendRepr::Vector { .. } | BackendRepr::Memory { .. } => { + false + } } } diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 8b9768859045..fc509704d0fd 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -475,7 +475,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { let layout = self.layout_of(tp_ty).layout; let use_integer_compare = match layout.backend_repr() { Scalar(_) | ScalarPair(_, _) => true, - Uninhabited | Vector { .. } => false, + Vector { .. } => false, Memory { .. } => { // For rusty ABIs, small aggregates are actually passed // as `RegKind::Integer` (see `FnAbi::adjust_for_abi`), diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index b0b6da869da6..ba01fbff3853 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -23,7 +23,7 @@ fn uncached_llvm_type<'a, 'tcx>( let element = layout.scalar_llvm_type_at(cx, element); return cx.type_vector(element, count); } - BackendRepr::Uninhabited | BackendRepr::Memory { .. } | BackendRepr::ScalarPair(..) => {} + BackendRepr::Memory { .. } | BackendRepr::ScalarPair(..) => {} } let name = match layout.ty.kind() { @@ -172,19 +172,16 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> { fn is_llvm_immediate(&self) -> bool { match self.backend_repr { BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => true, - BackendRepr::ScalarPair(..) | BackendRepr::Uninhabited | BackendRepr::Memory { .. } => { - false - } + BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => false, } } fn is_llvm_scalar_pair(&self) -> bool { match self.backend_repr { BackendRepr::ScalarPair(..) => true, - BackendRepr::Uninhabited - | BackendRepr::Scalar(_) - | BackendRepr::Vector { .. } - | BackendRepr::Memory { .. } => false, + BackendRepr::Scalar(_) | BackendRepr::Vector { .. } | BackendRepr::Memory { .. } => { + false + } } } diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 616d748a2995..1b88418fcf4f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -4,9 +4,7 @@ use rustc_abi::{BackendRepr, ExternAbi, HasDataLayout, Reg, WrappingRange}; use rustc_ast as ast; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_hir::lang_items::LangItem; -use rustc_middle::mir::{ - self, AssertKind, BasicBlock, InlineAsmMacro, SwitchTargets, UnwindTerminateReason, -}; +use rustc_middle::mir::{self, AssertKind, InlineAsmMacro, SwitchTargets, UnwindTerminateReason}; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement}; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::{self, Instance, Ty}; @@ -942,7 +940,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &fn_abi.ret, &mut llargs, Some(intrinsic), - target, ); let dest = match ret_dest { _ if fn_abi.ret.is_indirect() => llargs[0], @@ -998,19 +995,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }; let mut llargs = Vec::with_capacity(arg_count); - let destination = target.as_ref().map(|&target| { - ( - self.make_return_dest( - bx, - destination, - &fn_abi.ret, - &mut llargs, - None, - Some(target), - ), - target, - ) - }); + + // We still need to call `make_return_dest` even if there's no `target`, since + // `fn_abi.ret` could be `PassMode::Indirect`, even if it is uninhabited, + // and `make_return_dest` adds the return-place indirect pointer to `llargs`. + let return_dest = self.make_return_dest(bx, destination, &fn_abi.ret, &mut llargs, None); + let destination = target.map(|target| (return_dest, target)); // Split the rust-call tupled arguments off. let (first_args, untuple) = if abi == ExternAbi::RustCall && !args.is_empty() { @@ -1813,11 +1803,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { fn_ret: &ArgAbi<'tcx, Ty<'tcx>>, llargs: &mut Vec, intrinsic: Option, - target: Option, ) -> ReturnDest<'tcx, Bx::Value> { - if target.is_none() { - return ReturnDest::Nothing; - } // If the return is ignored, we can just return a do-nothing `ReturnDest`. if fn_ret.is_ignore() { return ReturnDest::Nothing; diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 9ca7d4f8f004..4616533bf993 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -415,10 +415,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { bx.store(*llval, llptr, field.align.abi); *llval = bx.load(llfield_ty, llptr, field.align.abi); } - ( - OperandValue::Immediate(_), - BackendRepr::Uninhabited | BackendRepr::Memory { sized: false }, - ) => { + (OperandValue::Immediate(_), BackendRepr::Memory { sized: false }) => { bug!() } (OperandValue::Pair(..), _) => bug!(), diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 5d905cff1f21..36da9037e43d 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -385,7 +385,7 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> { (Immediate::Uninit, _) => Immediate::Uninit, // If the field is uninhabited, we can forget the data (can happen in ConstProp). // `enum S { A(!), B, C }` is an example of an enum with Scalar layout that - // has an `Uninhabited` variant, which means this case is possible. + // has an uninhabited variant, which means this case is possible. _ if layout.is_uninhabited() => Immediate::Uninit, // the field contains no information, can be left uninit // (Scalar/ScalarPair can contain even aligned ZST, not just 1-ZST) diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 0ac34f4633b5..40dec0cb39e7 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -1264,21 +1264,20 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, } } - // *After* all of this, check the ABI. We need to check the ABI to handle - // types like `NonNull` where the `Scalar` info is more restrictive than what - // the fields say (`rustc_layout_scalar_valid_range_start`). - // But in most cases, this will just propagate what the fields say, - // and then we want the error to point at the field -- so, first recurse, - // then check ABI. + // *After* all of this, check further information stored in the layout. We need to check + // this to handle types like `NonNull` where the `Scalar` info is more restrictive than what + // the fields say (`rustc_layout_scalar_valid_range_start`). But in most cases, this will + // just propagate what the fields say, and then we want the error to point at the field -- + // so, we first recurse, then we do this check. // // FIXME: We could avoid some redundant checks here. For newtypes wrapping // scalars, we do the same check on every "level" (e.g., first we check // MyNewtype and then the scalar in there). + if val.layout.is_uninhabited() { + let ty = val.layout.ty; + throw_validation_failure!(self.path, UninhabitedVal { ty }); + } match val.layout.backend_repr { - BackendRepr::Uninhabited => { - let ty = val.layout.ty; - throw_validation_failure!(self.path, UninhabitedVal { ty }); - } BackendRepr::Scalar(scalar_layout) => { if !scalar_layout.is_uninit_valid() { // There is something to check here. diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs index 79baf91c3ce6..6426bca2332d 100644 --- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs +++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs @@ -111,13 +111,15 @@ fn check_validity_requirement_lax<'tcx>( }; // Check the ABI. - let valid = match this.backend_repr { - BackendRepr::Uninhabited => false, // definitely UB - BackendRepr::Scalar(s) => scalar_allows_raw_init(s), - BackendRepr::ScalarPair(s1, s2) => scalar_allows_raw_init(s1) && scalar_allows_raw_init(s2), - BackendRepr::Vector { element: s, count } => count == 0 || scalar_allows_raw_init(s), - BackendRepr::Memory { .. } => true, // Fields are checked below. - }; + let valid = !this.is_uninhabited() // definitely UB if uninhabited + && match this.backend_repr { + BackendRepr::Scalar(s) => scalar_allows_raw_init(s), + BackendRepr::ScalarPair(s1, s2) => { + scalar_allows_raw_init(s1) && scalar_allows_raw_init(s2) + } + BackendRepr::Vector { element: s, count } => count == 0 || scalar_allows_raw_init(s), + BackendRepr::Memory { .. } => true, // Fields are checked below. + }; if !valid { // This is definitely not okay. return Ok(false); diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index bbb8a9fa6714..36dfca22adf1 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -773,8 +773,9 @@ where Some(fields) => FieldsShape::Union(fields), None => FieldsShape::Arbitrary { offsets: IndexVec::new(), memory_index: IndexVec::new() }, }, - backend_repr: BackendRepr::Uninhabited, + backend_repr: BackendRepr::Memory { sized: true }, largest_niche: None, + uninhabited: true, align: tcx.data_layout.i8_align, size: Size::ZERO, max_repr_align: None, diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 77a3854ebdef..2f8a30501999 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -1558,8 +1558,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { return true; }; + if layout.uninhabited { + return true; + } + match layout.backend_repr { - BackendRepr::Uninhabited => true, BackendRepr::Scalar(a) => !a.is_always_valid(&self.ecx), BackendRepr::ScalarPair(a, b) => { !a.is_always_valid(&self.ecx) || !b.is_always_valid(&self.ecx) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 0962865e7f19..b37c684a0556 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -8,7 +8,7 @@ use rustc_ast::ptr::P; use rustc_ast::visit::{FnCtxt, FnKind, LifetimeCtxt, Visitor, walk_ty}; use rustc_ast::{ self as ast, AssocItemKind, DUMMY_NODE_ID, Expr, ExprKind, GenericParam, GenericParamKind, - Item, ItemKind, MethodCall, NodeId, Path, Ty, TyKind, + Item, ItemKind, MethodCall, NodeId, Path, PathSegment, Ty, TyKind, }; use rustc_ast_pretty::pprust::where_bound_predicate_to_string; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; @@ -1529,7 +1529,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { Applicability::MaybeIncorrect, ); true - } else if kind == DefKind::Struct + } else if matches!(kind, DefKind::Struct | DefKind::TyAlias) && let Some(lhs_source_span) = lhs_span.find_ancestor_inside(expr.span) && let Ok(snippet) = this.r.tcx.sess.source_map().span_to_snippet(lhs_source_span) { @@ -1566,7 +1566,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } }; - let mut bad_struct_syntax_suggestion = |this: &mut Self, def_id: DefId| { + let bad_struct_syntax_suggestion = |this: &mut Self, err: &mut Diag<'_>, def_id: DefId| { let (followed_by_brace, closing_brace) = this.followed_by_brace(span); match source { @@ -1740,12 +1740,10 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } } ( - Res::Def(kind @ (DefKind::Mod | DefKind::Trait), _), + Res::Def(kind @ (DefKind::Mod | DefKind::Trait | DefKind::TyAlias), _), PathSource::Expr(Some(parent)), - ) => { - if !path_sep(self, err, parent, kind) { - return false; - } + ) if path_sep(self, err, parent, kind) => { + return true; } ( Res::Def(DefKind::Enum, def_id), @@ -1777,13 +1775,13 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { let (ctor_def, ctor_vis, fields) = if let Some(struct_ctor) = struct_ctor { if let PathSource::Expr(Some(parent)) = source { if let ExprKind::Field(..) | ExprKind::MethodCall(..) = parent.kind { - bad_struct_syntax_suggestion(self, def_id); + bad_struct_syntax_suggestion(self, err, def_id); return true; } } struct_ctor } else { - bad_struct_syntax_suggestion(self, def_id); + bad_struct_syntax_suggestion(self, err, def_id); return true; }; @@ -1861,7 +1859,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { err.span_label(span, "constructor is not visible here due to private fields"); } (Res::Def(DefKind::Union | DefKind::Variant, def_id), _) if ns == ValueNS => { - bad_struct_syntax_suggestion(self, def_id); + bad_struct_syntax_suggestion(self, err, def_id); } (Res::Def(DefKind::Ctor(_, CtorKind::Const), def_id), _) if ns == ValueNS => { match source { @@ -2471,31 +2469,73 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { def_id: DefId, span: Span, ) { - let Some(variants) = self.collect_enum_ctors(def_id) else { + let Some(variant_ctors) = self.collect_enum_ctors(def_id) else { err.note("you might have meant to use one of the enum's variants"); return; }; - let suggest_only_tuple_variants = - matches!(source, PathSource::TupleStruct(..)) || source.is_call(); - if suggest_only_tuple_variants { + // If the expression is a field-access or method-call, try to find a variant with the field/method name + // that could have been intended, and suggest replacing the `.` with `::`. + // Otherwise, suggest adding `::VariantName` after the enum; + // and if the expression is call-like, only suggest tuple variants. + let (suggest_path_sep_dot_span, suggest_only_tuple_variants) = match source { + // `Type(a, b)` in a pattern, only suggest adding a tuple variant after `Type`. + PathSource::TupleStruct(..) => (None, true), + PathSource::Expr(Some(expr)) => match &expr.kind { + // `Type(a, b)`, only suggest adding a tuple variant after `Type`. + ExprKind::Call(..) => (None, true), + // `Type.Foo(a, b)`, suggest replacing `.` -> `::` if variant `Foo` exists and is a tuple variant, + // otherwise suggest adding a variant after `Type`. + ExprKind::MethodCall(box MethodCall { + receiver, + span, + seg: PathSegment { ident, .. }, + .. + }) => { + let dot_span = receiver.span.between(*span); + let found_tuple_variant = variant_ctors.iter().any(|(path, _, ctor_kind)| { + *ctor_kind == CtorKind::Fn + && path.segments.last().is_some_and(|seg| seg.ident == *ident) + }); + (found_tuple_variant.then_some(dot_span), false) + } + // `Type.Foo`, suggest replacing `.` -> `::` if variant `Foo` exists and is a unit or tuple variant, + // otherwise suggest adding a variant after `Type`. + ExprKind::Field(base, ident) => { + let dot_span = base.span.between(ident.span); + let found_tuple_or_unit_variant = variant_ctors.iter().any(|(path, ..)| { + path.segments.last().is_some_and(|seg| seg.ident == *ident) + }); + (found_tuple_or_unit_variant.then_some(dot_span), false) + } + _ => (None, false), + }, + _ => (None, false), + }; + + if let Some(dot_span) = suggest_path_sep_dot_span { + err.span_suggestion_verbose( + dot_span, + "use the path separator to refer to a variant", + "::", + Applicability::MaybeIncorrect, + ); + } else if suggest_only_tuple_variants { // Suggest only tuple variants regardless of whether they have fields and do not // suggest path with added parentheses. - let mut suggestable_variants = variants + let mut suggestable_variants = variant_ctors .iter() .filter(|(.., kind)| *kind == CtorKind::Fn) .map(|(variant, ..)| path_names_to_string(variant)) .collect::>(); suggestable_variants.sort(); - let non_suggestable_variant_count = variants.len() - suggestable_variants.len(); + let non_suggestable_variant_count = variant_ctors.len() - suggestable_variants.len(); - let source_msg = if source.is_call() { - "to construct" - } else if matches!(source, PathSource::TupleStruct(..)) { + let source_msg = if matches!(source, PathSource::TupleStruct(..)) { "to match against" } else { - unreachable!() + "to construct" }; if !suggestable_variants.is_empty() { @@ -2514,7 +2554,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } // If the enum has no tuple variants.. - if non_suggestable_variant_count == variants.len() { + if non_suggestable_variant_count == variant_ctors.len() { err.help(format!("the enum has no tuple variants {source_msg}")); } @@ -2537,7 +2577,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } }; - let mut suggestable_variants = variants + let mut suggestable_variants = variant_ctors .iter() .filter(|(_, def_id, kind)| !needs_placeholder(*def_id, *kind)) .map(|(variant, _, kind)| (path_names_to_string(variant), kind)) @@ -2564,7 +2604,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { ); } - let mut suggestable_variants_with_placeholders = variants + let mut suggestable_variants_with_placeholders = variant_ctors .iter() .filter(|(_, def_id, kind)| needs_placeholder(*def_id, *kind)) .map(|(variant, _, kind)| (path_names_to_string(variant), kind)) diff --git a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs index fb2e838cdc99..a627e0e69b62 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs @@ -202,7 +202,6 @@ impl<'tcx> Stable<'tcx> for rustc_abi::BackendRepr { fn stable(&self, tables: &mut Tables<'_>) -> Self::T { match *self { - rustc_abi::BackendRepr::Uninhabited => ValueAbi::Uninhabited, rustc_abi::BackendRepr::Scalar(scalar) => ValueAbi::Scalar(scalar.stable(tables)), rustc_abi::BackendRepr::ScalarPair(first, second) => { ValueAbi::ScalarPair(first.stable(tables), second.stable(tables)) diff --git a/compiler/rustc_target/src/callconv/loongarch.rs b/compiler/rustc_target/src/callconv/loongarch.rs index 47566bde6b4a..3fa67c624a7b 100644 --- a/compiler/rustc_target/src/callconv/loongarch.rs +++ b/compiler/rustc_target/src/callconv/loongarch.rs @@ -80,7 +80,7 @@ where } } }, - BackendRepr::Vector { .. } | BackendRepr::Uninhabited => return Err(CannotUseFpConv), + BackendRepr::Vector { .. } => return Err(CannotUseFpConv), BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => match arg_layout.fields { FieldsShape::Primitive => { unreachable!("aggregates can't have `FieldsShape::Primitive`") diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index 2bde10556221..0ea52c1aafb7 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -38,7 +38,7 @@ mod xtensa; pub enum PassMode { /// Ignore the argument. /// - /// The argument is either uninhabited or a ZST. + /// The argument is a ZST. Ignore, /// Pass the argument directly. /// @@ -350,7 +350,6 @@ impl<'a, Ty> ArgAbi<'a, Ty> { scalar_attrs: impl Fn(&TyAndLayout<'a, Ty>, Scalar, Size) -> ArgAttributes, ) -> Self { let mode = match layout.backend_repr { - BackendRepr::Uninhabited => PassMode::Ignore, BackendRepr::Scalar(scalar) => { PassMode::Direct(scalar_attrs(&layout, scalar, Size::ZERO)) } diff --git a/compiler/rustc_target/src/callconv/riscv.rs b/compiler/rustc_target/src/callconv/riscv.rs index 265ae20f9919..785175229b03 100644 --- a/compiler/rustc_target/src/callconv/riscv.rs +++ b/compiler/rustc_target/src/callconv/riscv.rs @@ -86,7 +86,7 @@ where } } }, - BackendRepr::Vector { .. } | BackendRepr::Uninhabited => return Err(CannotUseFpConv), + BackendRepr::Vector { .. } => return Err(CannotUseFpConv), BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => match arg_layout.fields { FieldsShape::Primitive => { unreachable!("aggregates can't have `FieldsShape::Primitive`") diff --git a/compiler/rustc_target/src/callconv/x86.rs b/compiler/rustc_target/src/callconv/x86.rs index 5b9414536d8c..4a9430bb80e7 100644 --- a/compiler/rustc_target/src/callconv/x86.rs +++ b/compiler/rustc_target/src/callconv/x86.rs @@ -108,9 +108,7 @@ where Ty: TyAbiInterface<'a, C> + Copy, { match layout.backend_repr { - BackendRepr::Uninhabited - | BackendRepr::Scalar(_) - | BackendRepr::ScalarPair(..) => false, + BackendRepr::Scalar(_) | BackendRepr::ScalarPair(..) => false, BackendRepr::Vector { .. } => true, BackendRepr::Memory { .. } => { for i in 0..layout.fields.count() { diff --git a/compiler/rustc_target/src/callconv/x86_64.rs b/compiler/rustc_target/src/callconv/x86_64.rs index b15d82c26dac..ab306e202396 100644 --- a/compiler/rustc_target/src/callconv/x86_64.rs +++ b/compiler/rustc_target/src/callconv/x86_64.rs @@ -51,8 +51,6 @@ where } let mut c = match layout.backend_repr { - BackendRepr::Uninhabited => return Ok(()), - BackendRepr::Scalar(scalar) => match scalar.primitive() { Primitive::Int(..) | Primitive::Pointer(_) => Class::Int, Primitive::Float(_) => Class::Sse, diff --git a/compiler/rustc_target/src/callconv/x86_win64.rs b/compiler/rustc_target/src/callconv/x86_win64.rs index 23ef2cf82840..1ee63d9200d9 100644 --- a/compiler/rustc_target/src/callconv/x86_win64.rs +++ b/compiler/rustc_target/src/callconv/x86_win64.rs @@ -8,7 +8,7 @@ use crate::spec::HasTargetSpec; pub(crate) fn compute_abi_info(_cx: &impl HasTargetSpec, fn_abi: &mut FnAbi<'_, Ty>) { let fixup = |a: &mut ArgAbi<'_, Ty>, is_ret: bool| { match a.layout.backend_repr { - BackendRepr::Uninhabited | BackendRepr::Memory { sized: false } => {} + BackendRepr::Memory { sized: false } => {} BackendRepr::ScalarPair(..) | BackendRepr::Memory { sized: true } => { match a.layout.size.bits() { 8 => a.cast_to(Reg::i8()), diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index c5d2d0afbfad..0ff82f0c256d 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -464,7 +464,7 @@ fn fn_abi_sanity_check<'tcx>( match &arg.mode { PassMode::Ignore => { - assert!(arg.layout.is_zst() || arg.layout.is_uninhabited()); + assert!(arg.layout.is_zst()); } PassMode::Direct(_) => { // Here the Rust type is used to determine the actual ABI, so we have to be very @@ -472,9 +472,7 @@ fn fn_abi_sanity_check<'tcx>( // `layout.backend_repr` and ignore everything else. We should just reject //`Aggregate` entirely here, but some targets need to be fixed first. match arg.layout.backend_repr { - BackendRepr::Uninhabited - | BackendRepr::Scalar(_) - | BackendRepr::Vector { .. } => {} + BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => {} BackendRepr::ScalarPair(..) => { panic!("`PassMode::Direct` used for ScalarPair type {}", arg.layout.ty) } diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 8429e68b600d..843a84a81bd5 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -364,19 +364,17 @@ fn layout_of_uncached<'tcx>( .checked_mul(count, dl) .ok_or_else(|| error(cx, LayoutError::SizeOverflow(ty)))?; - let abi = if count != 0 && ty.is_privately_uninhabited(tcx, cx.typing_env) { - BackendRepr::Uninhabited - } else { - BackendRepr::Memory { sized: true } - }; + let abi = BackendRepr::Memory { sized: true }; let largest_niche = if count != 0 { element.largest_niche } else { None }; + let uninhabited = if count != 0 { element.uninhabited } else { false }; tcx.mk_layout(LayoutData { variants: Variants::Single { index: FIRST_VARIANT }, fields: FieldsShape::Array { stride: element.size, count }, backend_repr: abi, largest_niche, + uninhabited, align: element.align, size, max_repr_align: None, @@ -391,6 +389,7 @@ fn layout_of_uncached<'tcx>( fields: FieldsShape::Array { stride: element.size, count: 0 }, backend_repr: BackendRepr::Memory { sized: false }, largest_niche: None, + uninhabited: false, align: element.align, size: Size::ZERO, max_repr_align: None, @@ -406,6 +405,7 @@ fn layout_of_uncached<'tcx>( fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 }, backend_repr: BackendRepr::Memory { sized: false }, largest_niche: None, + uninhabited: false, align: dl.i8_align, size: Size::ZERO, max_repr_align: None, @@ -584,6 +584,7 @@ fn layout_of_uncached<'tcx>( fields, backend_repr: abi, largest_niche: e_ly.largest_niche, + uninhabited: false, size, align, max_repr_align: None, @@ -1045,13 +1046,8 @@ fn coroutine_layout<'tcx>( size = size.align_to(align.abi); - let abi = if prefix.backend_repr.is_uninhabited() - || variants.iter().all(|v| v.backend_repr.is_uninhabited()) - { - BackendRepr::Uninhabited - } else { - BackendRepr::Memory { sized: true } - }; + let uninhabited = prefix.uninhabited || variants.iter().all(|v| v.is_uninhabited()); + let abi = BackendRepr::Memory { sized: true }; // this is similar to how ReprOptions populates its field_shuffle_seed let def_hash = tcx.def_path_hash(def_id).0.to_smaller_hash(); @@ -1072,6 +1068,7 @@ fn coroutine_layout<'tcx>( // See , . // FIXME: Remove when is implemented and aliased coroutine fields are wrapped in `UnsafePinned`. largest_niche: None, + uninhabited, size, align, max_repr_align: None, diff --git a/compiler/rustc_ty_utils/src/layout/invariant.rs b/compiler/rustc_ty_utils/src/layout/invariant.rs index 8d5403ed3246..5ea6716c5ca1 100644 --- a/compiler/rustc_ty_utils/src/layout/invariant.rs +++ b/compiler/rustc_ty_utils/src/layout/invariant.rs @@ -10,7 +10,11 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou // Type-level uninhabitedness should always imply ABI uninhabitedness. if layout.ty.is_privately_uninhabited(tcx, cx.typing_env) { - assert!(layout.is_uninhabited()); + assert!( + layout.is_uninhabited(), + "{:?} is type-level uninhabited but not ABI-uninhabited?", + layout.ty + ); } if layout.size.bytes() % layout.align.abi.bytes() != 0 { @@ -71,7 +75,7 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou let Some((align, size)) = align.zip(size) else { assert_matches!( layout.layout.backend_repr(), - BackendRepr::Uninhabited | BackendRepr::Memory { .. }, + BackendRepr::Memory { .. }, "ABI unexpectedly missing alignment and/or size in {layout:#?}" ); return; @@ -235,7 +239,7 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou assert!(align >= element.align(cx).abi); // just sanity-checking `vector_align`. // FIXME: Do some kind of check of the inner type, like for Scalar and ScalarPair. } - BackendRepr::Uninhabited | BackendRepr::Memory { .. } => {} // Nothing to check. + BackendRepr::Memory { .. } => {} // Nothing to check. } } @@ -291,8 +295,8 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou || variant.is_uninhabited() { // These are never actually accessed anyway, so we can skip the coherence check - // for them. They also fail that check, since they have - // `Aggregate`/`Uninhabited` ABI even when the main type is + // for them. They also fail that check, since they may have + // a different ABI even when the main type is // `Scalar`/`ScalarPair`. (Note that sometimes, variants with fields have size // 0, and sometimes, variants without fields have non-0 size.) continue; @@ -306,7 +310,6 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou (BackendRepr::ScalarPair(a1, b1), BackendRepr::ScalarPair(a2, b2)) => { scalar_coherent(a1, a2) && scalar_coherent(b1, b2) } - (BackendRepr::Uninhabited, _) => true, (BackendRepr::Memory { .. }, _) => true, _ => false, }; diff --git a/compiler/stable_mir/src/abi.rs b/compiler/stable_mir/src/abi.rs index 861b6692b536..091f3e1a95e9 100644 --- a/compiler/stable_mir/src/abi.rs +++ b/compiler/stable_mir/src/abi.rs @@ -227,7 +227,6 @@ pub enum TagEncoding { /// in terms of categories of C types there are ABI rules for. #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)] pub enum ValueAbi { - Uninhabited, Scalar(Scalar), ScalarPair(Scalar, Scalar), Vector { @@ -244,10 +243,7 @@ impl ValueAbi { /// Returns `true` if the layout corresponds to an unsized type. pub fn is_unsized(&self) -> bool { match *self { - ValueAbi::Uninhabited - | ValueAbi::Scalar(_) - | ValueAbi::ScalarPair(..) - | ValueAbi::Vector { .. } => false, + ValueAbi::Scalar(_) | ValueAbi::ScalarPair(..) | ValueAbi::Vector { .. } => false, ValueAbi::Aggregate { sized } => !sized, } } diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 154da6910788..686689868c4f 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -3155,6 +3155,24 @@ impl From for Vec { } } +#[stable(feature = "try_from_vec_u8_for_string", since = "CURRENT_RUSTC_VERSION")] +impl TryFrom> for String { + type Error = FromUtf8Error; + /// Converts the given [`Vec`] into a [`String`] if it contains valid UTF-8 data. + /// + /// # Examples + /// + /// ``` + /// let s1 = b"hello world".to_vec(); + /// let v1 = String::try_from(s1).unwrap(); + /// assert_eq!(v1, "hello world"); + /// + /// ``` + fn try_from(bytes: Vec) -> Result { + Self::from_utf8(bytes) + } +} + #[cfg(not(no_global_oom_handling))] #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Write for String { diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index ed45e26256e5..7b9a76e814a1 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -4796,7 +4796,7 @@ impl [[T; N]] { /// assert!(empty_slice_of_arrays.as_flattened().is_empty()); /// ``` #[stable(feature = "slice_flatten", since = "1.80.0")] - #[rustc_const_unstable(feature = "const_slice_flatten", issue = "95629")] + #[rustc_const_stable(feature = "const_slice_flatten", since = "CURRENT_RUSTC_VERSION")] pub const fn as_flattened(&self) -> &[T] { let len = if T::IS_ZST { self.len().checked_mul(N).expect("slice len overflow") @@ -4833,7 +4833,7 @@ impl [[T; N]] { /// assert_eq!(array, [[6, 7, 8], [9, 10, 11], [12, 13, 14]]); /// ``` #[stable(feature = "slice_flatten", since = "1.80.0")] - #[rustc_const_unstable(feature = "const_slice_flatten", issue = "95629")] + #[rustc_const_stable(feature = "const_slice_flatten", since = "CURRENT_RUSTC_VERSION")] pub const fn as_flattened_mut(&mut self) -> &mut [T] { let len = if T::IS_ZST { self.len().checked_mul(N).expect("slice len overflow") diff --git a/library/std/src/sys/os_str/bytes.rs b/library/std/src/sys/os_str/bytes.rs index 5b65d862be10..1d337694944b 100644 --- a/library/std/src/sys/os_str/bytes.rs +++ b/library/std/src/sys/os_str/bytes.rs @@ -8,7 +8,7 @@ use crate::collections::TryReserveError; use crate::fmt::Write; use crate::rc::Rc; use crate::sync::Arc; -use crate::sys_common::{AsInner, IntoInner}; +use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::{fmt, mem, str}; #[cfg(test)] @@ -25,6 +25,37 @@ pub struct Slice { pub inner: [u8], } +impl IntoInner> for Buf { + fn into_inner(self) -> Vec { + self.inner + } +} + +impl FromInner> for Buf { + fn from_inner(inner: Vec) -> Self { + Buf { inner } + } +} + +impl AsInner<[u8]> for Buf { + #[inline] + fn as_inner(&self) -> &[u8] { + &self.inner + } +} + +impl fmt::Debug for Buf { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(self.as_slice(), f) + } +} + +impl fmt::Display for Buf { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self.as_slice(), f) + } +} + impl fmt::Debug for Slice { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&self.inner.utf8_chunks().debug(), f) @@ -55,18 +86,6 @@ impl fmt::Display for Slice { } } -impl fmt::Debug for Buf { - fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(self.as_slice(), formatter) - } -} - -impl fmt::Display for Buf { - fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(self.as_slice(), formatter) - } -} - impl Clone for Buf { #[inline] fn clone(&self) -> Self { @@ -79,19 +98,6 @@ impl Clone for Buf { } } -impl IntoInner> for Buf { - fn into_inner(self) -> Vec { - self.inner - } -} - -impl AsInner<[u8]> for Buf { - #[inline] - fn as_inner(&self) -> &[u8] { - &self.inner - } -} - impl Buf { #[inline] pub fn into_encoded_bytes(self) -> Vec { @@ -103,6 +109,12 @@ impl Buf { Self { inner: s } } + #[inline] + pub fn into_string(self) -> Result { + String::from_utf8(self.inner).map_err(|p| Buf { inner: p.into_bytes() }) + } + + #[inline] pub fn from_string(s: String) -> Buf { Buf { inner: s.into_bytes() } } @@ -122,6 +134,11 @@ impl Buf { self.inner.capacity() } + #[inline] + pub fn push_slice(&mut self, s: &Slice) { + self.inner.extend_from_slice(&s.inner) + } + #[inline] pub fn reserve(&mut self, additional: usize) { self.inner.reserve(additional) @@ -157,7 +174,7 @@ impl Buf { // SAFETY: Slice just wraps [u8], // and &*self.inner is &[u8], therefore // transmuting &[u8] to &Slice is safe. - unsafe { mem::transmute(&*self.inner) } + unsafe { mem::transmute(self.inner.as_slice()) } } #[inline] @@ -165,15 +182,7 @@ impl Buf { // SAFETY: Slice just wraps [u8], // and &mut *self.inner is &mut [u8], therefore // transmuting &mut [u8] to &mut Slice is safe. - unsafe { mem::transmute(&mut *self.inner) } - } - - pub fn into_string(self) -> Result { - String::from_utf8(self.inner).map_err(|p| Buf { inner: p.into_bytes() }) - } - - pub fn push_slice(&mut self, s: &Slice) { - self.inner.extend_from_slice(&s.inner) + unsafe { mem::transmute(self.inner.as_mut_slice()) } } #[inline] @@ -278,18 +287,22 @@ impl Slice { unsafe { Slice::from_encoded_bytes_unchecked(s.as_bytes()) } } + #[inline] pub fn to_str(&self) -> Result<&str, crate::str::Utf8Error> { str::from_utf8(&self.inner) } + #[inline] pub fn to_string_lossy(&self) -> Cow<'_, str> { String::from_utf8_lossy(&self.inner) } + #[inline] pub fn to_owned(&self) -> Buf { Buf { inner: self.inner.to_vec() } } + #[inline] pub fn clone_into(&self, buf: &mut Buf) { self.inner.clone_into(&mut buf.inner) } @@ -300,6 +313,7 @@ impl Slice { unsafe { mem::transmute(boxed) } } + #[inline] pub fn empty_box() -> Box { let boxed: Box<[u8]> = Default::default(); unsafe { mem::transmute(boxed) } diff --git a/library/std/src/sys/os_str/wtf8.rs b/library/std/src/sys/os_str/wtf8.rs index a4ad5966afe5..19728d33990a 100644 --- a/library/std/src/sys/os_str/wtf8.rs +++ b/library/std/src/sys/os_str/wtf8.rs @@ -10,11 +10,16 @@ use crate::sys_common::wtf8::{Wtf8, Wtf8Buf, check_utf8_boundary}; use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::{fmt, mem}; -#[derive(Clone, Hash)] +#[derive(Hash)] pub struct Buf { pub inner: Wtf8Buf, } +#[repr(transparent)] +pub struct Slice { + pub inner: Wtf8, +} + impl IntoInner for Buf { fn into_inner(self) -> Wtf8Buf { self.inner @@ -35,31 +40,38 @@ impl AsInner for Buf { } impl fmt::Debug for Buf { - fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(self.as_slice(), formatter) + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(self.as_slice(), f) } } impl fmt::Display for Buf { - fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(self.as_slice(), formatter) + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self.as_slice(), f) } } -#[repr(transparent)] -pub struct Slice { - pub inner: Wtf8, -} - impl fmt::Debug for Slice { - fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(&self.inner, formatter) + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&self.inner, f) } } impl fmt::Display for Slice { - fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(&self.inner, formatter) + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&self.inner, f) + } +} + +impl Clone for Buf { + #[inline] + fn clone(&self) -> Self { + Buf { inner: self.inner.clone() } + } + + #[inline] + fn clone_from(&mut self, source: &Self) { + self.inner.clone_from(&source.inner) } } @@ -74,62 +86,57 @@ impl Buf { unsafe { Self { inner: Wtf8Buf::from_bytes_unchecked(s) } } } - pub fn with_capacity(capacity: usize) -> Buf { - Buf { inner: Wtf8Buf::with_capacity(capacity) } - } - - pub fn clear(&mut self) { - self.inner.clear() - } - - pub fn capacity(&self) -> usize { - self.inner.capacity() + #[inline] + pub fn into_string(self) -> Result { + self.inner.into_string().map_err(|buf| Buf { inner: buf }) } + #[inline] pub fn from_string(s: String) -> Buf { Buf { inner: Wtf8Buf::from_string(s) } } - pub fn as_slice(&self) -> &Slice { - // SAFETY: Slice is just a wrapper for Wtf8, - // and self.inner.as_slice() returns &Wtf8. - // Therefore, transmuting &Wtf8 to &Slice is safe. - unsafe { mem::transmute(self.inner.as_slice()) } + #[inline] + pub fn with_capacity(capacity: usize) -> Buf { + Buf { inner: Wtf8Buf::with_capacity(capacity) } } - pub fn as_mut_slice(&mut self) -> &mut Slice { - // SAFETY: Slice is just a wrapper for Wtf8, - // and self.inner.as_mut_slice() returns &mut Wtf8. - // Therefore, transmuting &mut Wtf8 to &mut Slice is safe. - // Additionally, care should be taken to ensure the slice - // is always valid Wtf8. - unsafe { mem::transmute(self.inner.as_mut_slice()) } + #[inline] + pub fn clear(&mut self) { + self.inner.clear() } - pub fn into_string(self) -> Result { - self.inner.into_string().map_err(|buf| Buf { inner: buf }) + #[inline] + pub fn capacity(&self) -> usize { + self.inner.capacity() } + #[inline] pub fn push_slice(&mut self, s: &Slice) { self.inner.push_wtf8(&s.inner) } + #[inline] pub fn reserve(&mut self, additional: usize) { self.inner.reserve(additional) } + #[inline] pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> { self.inner.try_reserve(additional) } + #[inline] pub fn reserve_exact(&mut self, additional: usize) { self.inner.reserve_exact(additional) } + #[inline] pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> { self.inner.try_reserve_exact(additional) } + #[inline] pub fn shrink_to_fit(&mut self) { self.inner.shrink_to_fit() } @@ -139,6 +146,24 @@ impl Buf { self.inner.shrink_to(min_capacity) } + #[inline] + pub fn as_slice(&self) -> &Slice { + // SAFETY: Slice is just a wrapper for Wtf8, + // and self.inner.as_slice() returns &Wtf8. + // Therefore, transmuting &Wtf8 to &Slice is safe. + unsafe { mem::transmute(self.inner.as_slice()) } + } + + #[inline] + pub fn as_mut_slice(&mut self) -> &mut Slice { + // SAFETY: Slice is just a wrapper for Wtf8, + // and self.inner.as_mut_slice() returns &mut Wtf8. + // Therefore, transmuting &mut Wtf8 to &mut Slice is safe. + // Additionally, care should be taken to ensure the slice + // is always valid Wtf8. + unsafe { mem::transmute(self.inner.as_mut_slice()) } + } + #[inline] pub fn leak<'a>(self) -> &'a mut Slice { unsafe { mem::transmute(self.inner.leak()) } @@ -194,6 +219,7 @@ impl Slice { } #[track_caller] + #[inline] pub fn check_public_boundary(&self, index: usize) { check_utf8_boundary(&self.inner, index); } @@ -203,18 +229,22 @@ impl Slice { unsafe { mem::transmute(Wtf8::from_str(s)) } } + #[inline] pub fn to_str(&self) -> Result<&str, crate::str::Utf8Error> { self.inner.as_str() } + #[inline] pub fn to_string_lossy(&self) -> Cow<'_, str> { self.inner.to_string_lossy() } + #[inline] pub fn to_owned(&self) -> Buf { Buf { inner: self.inner.to_owned() } } + #[inline] pub fn clone_into(&self, buf: &mut Buf) { self.inner.clone_into(&mut buf.inner) } @@ -224,6 +254,7 @@ impl Slice { unsafe { mem::transmute(self.inner.into_box()) } } + #[inline] pub fn empty_box() -> Box { unsafe { mem::transmute(Wtf8::empty_box()) } } diff --git a/library/std/src/sys_common/wtf8.rs b/library/std/src/sys_common/wtf8.rs index 6c60d901ee90..f4402fc6f986 100644 --- a/library/std/src/sys_common/wtf8.rs +++ b/library/std/src/sys_common/wtf8.rs @@ -156,9 +156,12 @@ impl ops::DerefMut for Wtf8Buf { } } -/// Format the string with double quotes, -/// and surrogates as `\u` followed by four hexadecimal digits. -/// Example: `"a\u{D800}"` for a string with code points [U+0061, U+D800] +/// Formats the string in double quotes, with characters escaped according to +/// [`char::escape_debug`] and unpaired surrogates represented as `\u{xxxx}`, +/// where each `x` is a hexadecimal digit. +/// +/// For example, the code units [U+0061, U+D800, U+000A] are formatted as +/// `"a\u{D800}\n"`. impl fmt::Debug for Wtf8Buf { #[inline] fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -181,7 +184,7 @@ impl Wtf8Buf { /// Creates a WTF-8 string from a WTF-8 byte vec. /// - /// Since the byte vec is not checked for valid WTF-8, this functions is + /// Since the byte vec is not checked for valid WTF-8, this function is /// marked unsafe. #[inline] pub unsafe fn from_bytes_unchecked(value: Vec) -> Wtf8Buf { @@ -205,7 +208,7 @@ impl Wtf8Buf { /// Since WTF-8 is a superset of UTF-8, this always succeeds. #[inline] pub fn from_str(s: &str) -> Wtf8Buf { - Wtf8Buf { bytes: <[_]>::to_vec(s.as_bytes()), is_known_utf8: true } + Wtf8Buf { bytes: s.as_bytes().to_vec(), is_known_utf8: true } } pub fn clear(&mut self) { @@ -237,8 +240,9 @@ impl Wtf8Buf { string } - /// Copied from String::push + /// Appends the given `char` to the end of this string. /// This does **not** include the WTF-8 concatenation check or `is_known_utf8` check. + /// Copied from String::push. fn push_code_point_unchecked(&mut self, code_point: CodePoint) { let mut bytes = [0; 4]; let bytes = encode_utf8_raw(code_point.value, &mut bytes); @@ -264,16 +268,16 @@ impl Wtf8Buf { /// /// # Panics /// - /// Panics if the new capacity overflows `usize`. + /// Panics if the new capacity exceeds `isize::MAX` bytes. #[inline] pub fn reserve(&mut self, additional: usize) { self.bytes.reserve(additional) } - /// Tries to reserve capacity for at least `additional` more length units - /// in the given `Wtf8Buf`. The `Wtf8Buf` may reserve more space to avoid - /// frequent reallocations. After calling `try_reserve`, capacity will be - /// greater than or equal to `self.len() + additional`. Does nothing if + /// Tries to reserve capacity for at least `additional` more bytes to be + /// inserted in the given `Wtf8Buf`. The `Wtf8Buf` may reserve more space to + /// avoid frequent reallocations. After calling `try_reserve`, capacity will + /// be greater than or equal to `self.len() + additional`. Does nothing if /// capacity is already sufficient. This method preserves the contents even /// if an error occurs. /// @@ -291,8 +295,8 @@ impl Wtf8Buf { self.bytes.reserve_exact(additional) } - /// Tries to reserve the minimum capacity for exactly `additional` - /// length units in the given `Wtf8Buf`. After calling + /// Tries to reserve the minimum capacity for exactly `additional` more + /// bytes to be inserted in the given `Wtf8Buf`. After calling /// `try_reserve_exact`, capacity will be greater than or equal to /// `self.len() + additional` if it returns `Ok(())`. /// Does nothing if the capacity is already sufficient. @@ -440,22 +444,17 @@ impl Wtf8Buf { /// /// Surrogates are replaced with `"\u{FFFD}"` (the replacement character “�”) pub fn into_string_lossy(mut self) -> String { - // Fast path: If we already have UTF-8, we can return it immediately. - if self.is_known_utf8 { - return unsafe { String::from_utf8_unchecked(self.bytes) }; - } - - let mut pos = 0; - loop { - match self.next_surrogate(pos) { - Some((surrogate_pos, _)) => { - pos = surrogate_pos + 3; - self.bytes[surrogate_pos..pos] - .copy_from_slice(UTF8_REPLACEMENT_CHARACTER.as_bytes()); - } - None => return unsafe { String::from_utf8_unchecked(self.bytes) }, + if !self.is_known_utf8 { + let mut pos = 0; + while let Some((surrogate_pos, _)) = self.next_surrogate(pos) { + pos = surrogate_pos + 3; + // Surrogates and the replacement character are all 3 bytes, so + // they can substituted in-place. + self.bytes[surrogate_pos..pos] + .copy_from_slice(UTF8_REPLACEMENT_CHARACTER.as_bytes()); } } + unsafe { String::from_utf8_unchecked(self.bytes) } } /// Converts this `Wtf8Buf` into a boxed `Wtf8`. @@ -535,9 +534,9 @@ impl AsInner<[u8]> for Wtf8 { } } -/// Format the slice with double quotes, -/// and surrogates as `\u` followed by four hexadecimal digits. -/// Example: `"a\u{D800}"` for a slice with code points [U+0061, U+D800] +/// Formats the string in double quotes, with characters escaped according to +/// [`char::escape_debug`] and unpaired surrogates represented as `\u{xxxx}`, +/// where each `x` is a hexadecimal digit. impl fmt::Debug for Wtf8 { fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { fn write_str_escaped(f: &mut fmt::Formatter<'_>, s: &str) -> fmt::Result { @@ -562,6 +561,8 @@ impl fmt::Debug for Wtf8 { } } +/// Formats the string with unpaired surrogates substituted with the replacement +/// character, U+FFFD. impl fmt::Display for Wtf8 { fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { let wtf8_bytes = &self.bytes; @@ -672,9 +673,8 @@ impl Wtf8 { /// /// This only copies the data if necessary (if it contains any surrogate). pub fn to_string_lossy(&self) -> Cow<'_, str> { - let surrogate_pos = match self.next_surrogate(0) { - None => return Cow::Borrowed(unsafe { str::from_utf8_unchecked(&self.bytes) }), - Some((pos, _)) => pos, + let Some((surrogate_pos, _)) = self.next_surrogate(0) else { + return Cow::Borrowed(unsafe { str::from_utf8_unchecked(&self.bytes) }); }; let wtf8_bytes = &self.bytes; let mut utf8_bytes = Vec::with_capacity(self.len()); @@ -964,7 +964,7 @@ pub struct Wtf8CodePoints<'a> { bytes: slice::Iter<'a, u8>, } -impl<'a> Iterator for Wtf8CodePoints<'a> { +impl Iterator for Wtf8CodePoints<'_> { type Item = CodePoint; #[inline] @@ -990,7 +990,7 @@ pub struct EncodeWide<'a> { // Copied from libunicode/u_str.rs #[stable(feature = "rust1", since = "1.0.0")] -impl<'a> Iterator for EncodeWide<'a> { +impl Iterator for EncodeWide<'_> { type Item = u16; #[inline] diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs index fbd0dc3ec302..f25dfaab0f11 100644 --- a/src/bootstrap/src/core/build_steps/setup.rs +++ b/src/bootstrap/src/core/build_steps/setup.rs @@ -523,19 +523,31 @@ undesirable, simply delete the `pre-push` file from .git/hooks." /// Handles editor-specific setup differences #[derive(Clone, Debug, Eq, PartialEq)] enum EditorKind { - Vscode, - Vim, Emacs, Helix, + Vim, + VsCode, + Zed, } impl EditorKind { + // Used in `./tests.rs`. + #[allow(dead_code)] + pub const ALL: &[EditorKind] = &[ + EditorKind::Emacs, + EditorKind::Helix, + EditorKind::Vim, + EditorKind::VsCode, + EditorKind::Zed, + ]; + fn prompt_user() -> io::Result> { let prompt_str = "Available editors: -1. vscode -2. vim -3. emacs -4. helix +1. Emacs +2. Helix +3. Vim +4. VS Code +5. Zed Select which editor you would like to set up [default: None]: "; @@ -543,28 +555,41 @@ Select which editor you would like to set up [default: None]: "; loop { print!("{}", prompt_str); io::stdout().flush()?; - input.clear(); io::stdin().read_line(&mut input)?; - match input.trim().to_lowercase().as_str() { - "1" | "vscode" => return Ok(Some(EditorKind::Vscode)), - "2" | "vim" => return Ok(Some(EditorKind::Vim)), - "3" | "emacs" => return Ok(Some(EditorKind::Emacs)), - "4" | "helix" => return Ok(Some(EditorKind::Helix)), - "" => return Ok(None), + + let mut modified_input = input.to_lowercase(); + modified_input.retain(|ch| !ch.is_whitespace()); + match modified_input.as_str() { + "1" | "emacs" => return Ok(Some(EditorKind::Emacs)), + "2" | "helix" => return Ok(Some(EditorKind::Helix)), + "3" | "vim" => return Ok(Some(EditorKind::Vim)), + "4" | "vscode" => return Ok(Some(EditorKind::VsCode)), + "5" | "zed" => return Ok(Some(EditorKind::Zed)), + "" | "none" => return Ok(None), _ => { eprintln!("ERROR: unrecognized option '{}'", input.trim()); eprintln!("NOTE: press Ctrl+C to exit"); } - }; + } + + input.clear(); } } /// A list of historical hashes of each LSP settings file /// New entries should be appended whenever this is updated so we can detect /// outdated vs. user-modified settings files. - fn hashes(&self) -> Vec<&str> { + fn hashes(&self) -> &'static [&'static str] { match self { - EditorKind::Vscode | EditorKind::Vim => vec![ + EditorKind::Emacs => &[ + "51068d4747a13732440d1a8b8f432603badb1864fa431d83d0fd4f8fa57039e0", + "d29af4d949bbe2371eac928a3c31cf9496b1701aa1c45f11cd6c759865ad5c45", + ], + EditorKind::Helix => &[ + "2d3069b8cf1b977e5d4023965eb6199597755e6c96c185ed5f2854f98b83d233", + "6736d61409fbebba0933afd2e4c44ff2f97c1cb36cf0299a7f4a7819b8775040", + ], + EditorKind::Vim | EditorKind::VsCode => &[ "ea67e259dedf60d4429b6c349a564ffcd1563cf41c920a856d1f5b16b4701ac8", "56e7bf011c71c5d81e0bf42e84938111847a810eee69d906bba494ea90b51922", "af1b5efe196aed007577899db9dae15d6dbc923d6fa42fa0934e68617ba9bbe0", @@ -576,12 +601,8 @@ Select which editor you would like to set up [default: None]: "; "4eecb58a2168b252077369da446c30ed0e658301efe69691979d1ef0443928f4", "c394386e6133bbf29ffd32c8af0bb3d4aac354cba9ee051f29612aa9350f8f8d", ], - EditorKind::Emacs => vec![ - "51068d4747a13732440d1a8b8f432603badb1864fa431d83d0fd4f8fa57039e0", - "d29af4d949bbe2371eac928a3c31cf9496b1701aa1c45f11cd6c759865ad5c45", - ], - EditorKind::Helix => { - vec!["2d3069b8cf1b977e5d4023965eb6199597755e6c96c185ed5f2854f98b83d233"] + EditorKind::Zed => { + &["bbce727c269d1bd0c98afef4d612eb4ce27aea3c3a8968c5f10b31affbc40b6c"] } } } @@ -592,29 +613,31 @@ Select which editor you would like to set up [default: None]: "; fn settings_short_path(&self) -> PathBuf { self.settings_folder().join(match self { - EditorKind::Vscode => "settings.json", - EditorKind::Vim => "coc-settings.json", EditorKind::Emacs => ".dir-locals.el", EditorKind::Helix => "languages.toml", + EditorKind::Vim => "coc-settings.json", + EditorKind::VsCode | EditorKind::Zed => "settings.json", }) } fn settings_folder(&self) -> PathBuf { match self { - EditorKind::Vscode => PathBuf::from(".vscode"), - EditorKind::Vim => PathBuf::from(".vim"), EditorKind::Emacs => PathBuf::new(), EditorKind::Helix => PathBuf::from(".helix"), + EditorKind::Vim => PathBuf::from(".vim"), + EditorKind::VsCode => PathBuf::from(".vscode"), + EditorKind::Zed => PathBuf::from(".zed"), } } - fn settings_template(&self) -> &str { + fn settings_template(&self) -> &'static str { match self { - EditorKind::Vscode | EditorKind::Vim => { - include_str!("../../../../etc/rust_analyzer_settings.json") - } EditorKind::Emacs => include_str!("../../../../etc/rust_analyzer_eglot.el"), EditorKind::Helix => include_str!("../../../../etc/rust_analyzer_helix.toml"), + EditorKind::Vim | EditorKind::VsCode => { + include_str!("../../../../etc/rust_analyzer_settings.json") + } + EditorKind::Zed => include_str!("../../../../etc/rust_analyzer_zed.json"), } } diff --git a/src/bootstrap/src/core/build_steps/setup/tests.rs b/src/bootstrap/src/core/build_steps/setup/tests.rs index f3d4b6aa4db6..e8f83ff75e40 100644 --- a/src/bootstrap/src/core/build_steps/setup/tests.rs +++ b/src/bootstrap/src/core/build_steps/setup/tests.rs @@ -5,13 +5,16 @@ use crate::utils::helpers::hex_encode; #[test] fn check_matching_settings_hash() { - let editor = EditorKind::Vscode; - let mut hasher = sha2::Sha256::new(); - hasher.update(&editor.settings_template()); - let hash = hex_encode(hasher.finalize().as_slice()); - assert_eq!( - &hash, - editor.hashes().last().unwrap(), - "Update `EditorKind::hashes()` with the new hash of `src/etc/rust_analyzer_settings.json`" - ); + for editor in EditorKind::ALL { + let mut hasher = sha2::Sha256::new(); + hasher.update(&editor.settings_template()); + let hash = hex_encode(hasher.finalize().as_slice()); + assert_eq!( + &hash, + editor.hashes().last().unwrap(), + "Update `EditorKind::hashes()` with the new hash of `{}` for `EditorKind::{:?}`", + editor.settings_template(), + editor, + ); + } } diff --git a/src/doc/rustc-dev-guide/src/building/suggested.md b/src/doc/rustc-dev-guide/src/building/suggested.md index 2c6c3fe1df84..5c041d6cb70f 100644 --- a/src/doc/rustc-dev-guide/src/building/suggested.md +++ b/src/doc/rustc-dev-guide/src/building/suggested.md @@ -154,6 +154,16 @@ You can run `./x setup editor` and select `helix`, which will prompt you to create `languages.toml` with the recommended configuration for Helix. The recommended settings live at [`src/etc/rust_analyzer_helix.toml`]. +### Zed + +Zed comes with built-in LSP and rust-analyzer support. +It can be configured through `.zed/settings.json`, as described +[here](https://zed.dev/docs/configuring-languages). Selecting `zed` +in `./x setup editor` will prompt you to create a `.zed/settings.json` +file which will configure Zed with the recommended configuration. The +recommended `rust-analyzer` settings live +at [`src/etc/rust_analyzer_zed.json`]. + ## Check, check, and check again When doing simple refactoring, it can be useful to run `./x check` @@ -381,4 +391,5 @@ load this completion. [`src/etc/rust_analyzer_settings.json`]: https://github.com/rust-lang/rust/blob/master/src/etc/rust_analyzer_settings.json [`src/etc/rust_analyzer_eglot.el`]: https://github.com/rust-lang/rust/blob/master/src/etc/rust_analyzer_eglot.el [`src/etc/rust_analyzer_helix.toml`]: https://github.com/rust-lang/rust/blob/master/src/etc/rust_analyzer_helix.toml +[`src/etc/rust_analyzer_zed.json`]: https://github.com/rust-lang/rust/blob/master/src/etc/rust_analyzer_zed.json [`src/etc/pre-push.sh`]: https://github.com/rust-lang/rust/blob/master/src/etc/pre-push.sh diff --git a/src/doc/rustc-dev-guide/src/implementing_new_features.md b/src/doc/rustc-dev-guide/src/implementing_new_features.md index 5b67ccd7f4c5..fda38ef4fc01 100644 --- a/src/doc/rustc-dev-guide/src/implementing_new_features.md +++ b/src/doc/rustc-dev-guide/src/implementing_new_features.md @@ -167,9 +167,7 @@ a new unstable feature: 1. Prevent usage of the new feature unless the feature gate is set. You can check it in most places in the compiler using the - expression `tcx.features().$feature_name` (or - `sess.features_untracked().$feature_name` if the - tcx is unavailable) + expression `tcx.features().$feature_name()` If the feature gate is not set, you should either maintain the pre-feature behavior or raise an error, depending on diff --git a/src/etc/rust_analyzer_zed.json b/src/etc/rust_analyzer_zed.json new file mode 100644 index 000000000000..469ea0506218 --- /dev/null +++ b/src/etc/rust_analyzer_zed.json @@ -0,0 +1,52 @@ +{ + "lsp": { + "rust-analyzer": { + "initialization_options": { + "cargo": { + "buildScripts": { + "enable": true, + "invocationLocation": "root", + "invocationStrategy": "once", + "overrideCommand": ["python3", "x.py", "check", "--json-output"] + }, + "extraEnv": { + "RUSTC_BOOTSTRAP": "1" + }, + "sysrootSrc": "./library" + }, + "check": { + "invocationLocation": "root", + "invocationStrategy": "once", + "overrideCommand": ["python3", "x.py", "check", "--json-output"] + }, + "linkedProjects": [ + "Cargo.toml", + "library/Cargo.toml", + "src/tools/x/Cargo.toml", + "src/bootstrap/Cargo.toml", + "src/tools/rust-analyzer/Cargo.toml", + "compiler/rustc_codegen_cranelift/Cargo.toml", + "compiler/rustc_codegen_gcc/Cargo.toml" + ], + "procMacro": { + "enable": true, + "server": "${workspaceFolder}/build/host/stage0/libexec/rust-analyzer-proc-macro-srv" + }, + "rustc": { + "source": "./Cargo.toml" + }, + "rustfmt": { + "overrideCommand": [ + "${workspaceFolder}/build/host/rustfmt/bin/rustfmt", + "--edition=2021" + ] + }, + "server": { + "extraEnv": { + "RUSTUP_TOOLCHAIN": "nightly" + } + } + } + } + } +} diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs index b6f7c44c2aee..f5a7b6581230 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs @@ -194,6 +194,7 @@ fn layout_of_simd_ty( fields, backend_repr: BackendRepr::Vector { element: e_abi, count: e_len }, largest_niche: e_ly.largest_niche, + uninhabited: false, size, align, max_repr_align: None, @@ -297,20 +298,17 @@ pub fn layout_of_ty_query( .checked_mul(count, dl) .ok_or(LayoutError::BadCalc(LayoutCalculatorError::SizeOverflow))?; - let backend_repr = - if count != 0 && matches!(element.backend_repr, BackendRepr::Uninhabited) { - BackendRepr::Uninhabited - } else { - BackendRepr::Memory { sized: true } - }; + let backend_repr = BackendRepr::Memory { sized: true }; let largest_niche = if count != 0 { element.largest_niche } else { None }; + let uninhabited = if count != 0 { element.uninhabited } else { false }; Layout { variants: Variants::Single { index: struct_variant_idx() }, fields: FieldsShape::Array { stride: element.size, count }, backend_repr, largest_niche, + uninhabited, align: element.align, size, max_repr_align: None, @@ -325,6 +323,7 @@ pub fn layout_of_ty_query( fields: FieldsShape::Array { stride: element.size, count: 0 }, backend_repr: BackendRepr::Memory { sized: false }, largest_niche: None, + uninhabited: false, align: element.align, size: Size::ZERO, max_repr_align: None, @@ -337,6 +336,7 @@ pub fn layout_of_ty_query( fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 }, backend_repr: BackendRepr::Memory { sized: false }, largest_niche: None, + uninhabited: false, align: dl.i8_align, size: Size::ZERO, max_repr_align: None, diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index 39c9a148e9e5..1cb47353469f 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -3619,7 +3619,6 @@ ui/resolve/issue-21221-1.rs ui/resolve/issue-21221-2.rs ui/resolve/issue-21221-3.rs ui/resolve/issue-21221-4.rs -ui/resolve/issue-22692.rs ui/resolve/issue-2330.rs ui/resolve/issue-23305.rs ui/resolve/issue-2356.rs diff --git a/tests/codegen/uninhabited-transparent-return-abi.rs b/tests/codegen/uninhabited-transparent-return-abi.rs new file mode 100644 index 000000000000..3c0b92f61d0b --- /dev/null +++ b/tests/codegen/uninhabited-transparent-return-abi.rs @@ -0,0 +1,42 @@ +// See https://github.com/rust-lang/rust/issues/135802 + +#![crate_type = "lib"] + +enum Void {} + +// Should be ABI-compatible with T, but wasn't prior to the PR adding this test. +#[repr(transparent)] +struct NoReturn(T, Void); + +// Returned by invisible reference (in most ABIs) +#[allow(dead_code)] +struct Large(u64, u64, u64); + +extern "Rust" { + fn opaque() -> NoReturn; + fn opaque_with_arg(rsi: u32) -> NoReturn; +} + +// CHECK-LABEL: @test_uninhabited_ret_by_ref +#[no_mangle] +pub fn test_uninhabited_ret_by_ref() { + // CHECK: %_1 = alloca [24 x i8], align {{8|4}} + // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %_1) + // CHECK-NEXT: call void @opaque(ptr noalias nocapture noundef nonnull sret([24 x i8]) align {{8|4}} dereferenceable(24) %_1) #2 + // CHECK-NEXT: unreachable + unsafe { + opaque(); + } +} + +// CHECK-LABEL: @test_uninhabited_ret_by_ref_with_arg +#[no_mangle] +pub fn test_uninhabited_ret_by_ref_with_arg(rsi: u32) { + // CHECK: %_2 = alloca [24 x i8], align {{8|4}} + // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %_2) + // CHECK-NEXT: call void @opaque_with_arg(ptr noalias nocapture noundef nonnull sret([24 x i8]) align {{8|4}} dereferenceable(24) %_2, i32 noundef %rsi) #2 + // CHECK-NEXT: unreachable + unsafe { + opaque_with_arg(rsi); + } +} diff --git a/tests/ui/abi/c-zst.aarch64-darwin.stderr b/tests/ui/abi/c-zst.aarch64-darwin.stderr index c8f7d0a517c4..57cc48aa9cf4 100644 --- a/tests/ui/abi/c-zst.aarch64-darwin.stderr +++ b/tests/ui/abi/c-zst.aarch64-darwin.stderr @@ -17,6 +17,7 @@ error: fn_abi_of(pass_zst) = FnAbi { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -45,6 +46,7 @@ error: fn_abi_of(pass_zst) = FnAbi { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, diff --git a/tests/ui/abi/c-zst.powerpc-linux.stderr b/tests/ui/abi/c-zst.powerpc-linux.stderr index 1015f7d88988..673801767300 100644 --- a/tests/ui/abi/c-zst.powerpc-linux.stderr +++ b/tests/ui/abi/c-zst.powerpc-linux.stderr @@ -17,6 +17,7 @@ error: fn_abi_of(pass_zst) = FnAbi { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -56,6 +57,7 @@ error: fn_abi_of(pass_zst) = FnAbi { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, diff --git a/tests/ui/abi/c-zst.s390x-linux.stderr b/tests/ui/abi/c-zst.s390x-linux.stderr index 1015f7d88988..673801767300 100644 --- a/tests/ui/abi/c-zst.s390x-linux.stderr +++ b/tests/ui/abi/c-zst.s390x-linux.stderr @@ -17,6 +17,7 @@ error: fn_abi_of(pass_zst) = FnAbi { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -56,6 +57,7 @@ error: fn_abi_of(pass_zst) = FnAbi { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, diff --git a/tests/ui/abi/c-zst.sparc64-linux.stderr b/tests/ui/abi/c-zst.sparc64-linux.stderr index 1015f7d88988..673801767300 100644 --- a/tests/ui/abi/c-zst.sparc64-linux.stderr +++ b/tests/ui/abi/c-zst.sparc64-linux.stderr @@ -17,6 +17,7 @@ error: fn_abi_of(pass_zst) = FnAbi { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -56,6 +57,7 @@ error: fn_abi_of(pass_zst) = FnAbi { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, diff --git a/tests/ui/abi/c-zst.x86_64-linux.stderr b/tests/ui/abi/c-zst.x86_64-linux.stderr index c8f7d0a517c4..57cc48aa9cf4 100644 --- a/tests/ui/abi/c-zst.x86_64-linux.stderr +++ b/tests/ui/abi/c-zst.x86_64-linux.stderr @@ -17,6 +17,7 @@ error: fn_abi_of(pass_zst) = FnAbi { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -45,6 +46,7 @@ error: fn_abi_of(pass_zst) = FnAbi { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, diff --git a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr index 1015f7d88988..673801767300 100644 --- a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr +++ b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr @@ -17,6 +17,7 @@ error: fn_abi_of(pass_zst) = FnAbi { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -56,6 +57,7 @@ error: fn_abi_of(pass_zst) = FnAbi { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, diff --git a/tests/ui/abi/debug.stderr b/tests/ui/abi/debug.stderr index e550e5bfcf3c..5f73ff7d6bd5 100644 --- a/tests/ui/abi/debug.stderr +++ b/tests/ui/abi/debug.stderr @@ -20,6 +20,7 @@ error: fn_abi_of(test) = FnAbi { ), fields: Primitive, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -67,6 +68,7 @@ error: fn_abi_of(test) = FnAbi { valid_range: 0..=1, }, ), + uninhabited: false, variants: Single { index: 0, }, @@ -125,6 +127,7 @@ error: fn_abi_of(TestFnPtr) = FnAbi { valid_range: 0..=1, }, ), + uninhabited: false, variants: Single { index: 0, }, @@ -163,6 +166,7 @@ error: fn_abi_of(TestFnPtr) = FnAbi { ), fields: Primitive, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -213,6 +217,7 @@ error: fn_abi_of(test_generic) = FnAbi { ), fields: Primitive, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -248,6 +253,7 @@ error: fn_abi_of(test_generic) = FnAbi { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -297,6 +303,7 @@ error: ABIs are not compatible ), fields: Primitive, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -332,6 +339,7 @@ error: ABIs are not compatible memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -369,6 +377,7 @@ error: ABIs are not compatible ), fields: Primitive, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -404,6 +413,7 @@ error: ABIs are not compatible memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -444,6 +454,7 @@ error: ABIs are not compatible count: 32, }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -483,6 +494,7 @@ error: ABIs are not compatible memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -517,6 +529,7 @@ error: ABIs are not compatible count: 32, }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -556,6 +569,7 @@ error: ABIs are not compatible memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -598,6 +612,7 @@ error: ABIs are not compatible ), fields: Primitive, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -633,6 +648,7 @@ error: ABIs are not compatible memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -670,6 +686,7 @@ error: ABIs are not compatible ), fields: Primitive, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -705,6 +722,7 @@ error: ABIs are not compatible memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -748,6 +766,7 @@ error: ABIs are not compatible ), fields: Primitive, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -783,6 +802,7 @@ error: ABIs are not compatible memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -820,6 +840,7 @@ error: ABIs are not compatible ), fields: Primitive, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -855,6 +876,7 @@ error: ABIs are not compatible memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -923,6 +945,7 @@ error: fn_abi_of(assoc_test) = FnAbi { valid_range: $NON_NULL, }, ), + uninhabited: false, variants: Single { index: 0, }, @@ -960,6 +983,7 @@ error: fn_abi_of(assoc_test) = FnAbi { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, diff --git a/tests/ui/abi/sysv64-zst.stderr b/tests/ui/abi/sysv64-zst.stderr index 781e9b2f4c9d..ec85030c1068 100644 --- a/tests/ui/abi/sysv64-zst.stderr +++ b/tests/ui/abi/sysv64-zst.stderr @@ -17,6 +17,7 @@ error: fn_abi_of(pass_zst) = FnAbi { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -45,6 +46,7 @@ error: fn_abi_of(pass_zst) = FnAbi { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, diff --git a/tests/ui/layout/debug.stderr b/tests/ui/layout/debug.stderr index 319c0de26a90..e3d37030ce47 100644 --- a/tests/ui/layout/debug.stderr +++ b/tests/ui/layout/debug.stderr @@ -31,6 +31,7 @@ error: layout_of(E) = Layout { valid_range: 0..=0, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -56,6 +57,7 @@ error: layout_of(E) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -69,7 +71,9 @@ error: layout_of(E) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: Memory { + sized: true, + }, fields: Arbitrary { offsets: [ Size(4 bytes), @@ -83,6 +87,7 @@ error: layout_of(E) = Layout { ], }, largest_niche: None, + uninhabited: true, variants: Single { index: 1, }, @@ -136,6 +141,7 @@ error: layout_of(S) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -161,6 +167,7 @@ error: layout_of(U) = Layout { 2, ), largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -213,6 +220,7 @@ error: layout_of(Result) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -255,6 +263,7 @@ error: layout_of(Result) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -293,6 +302,7 @@ error: layout_of(Result) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, @@ -328,6 +338,7 @@ error: layout_of(i32) = Layout { ), fields: Primitive, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -353,6 +364,7 @@ error: layout_of(V) = Layout { 2, ), largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -378,6 +390,7 @@ error: layout_of(W) = Layout { 2, ), largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -403,6 +416,7 @@ error: layout_of(Y) = Layout { 2, ), largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -428,6 +442,7 @@ error: layout_of(P1) = Layout { 1, ), largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -453,6 +468,7 @@ error: layout_of(P2) = Layout { 1, ), largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -478,6 +494,7 @@ error: layout_of(P3) = Layout { 1, ), largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -503,6 +520,7 @@ error: layout_of(P4) = Layout { 1, ), largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -533,6 +551,7 @@ error: layout_of(P5) = Layout { 2, ), largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -563,6 +582,7 @@ error: layout_of(MaybeUninit) = Layout { 2, ), largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, diff --git a/tests/ui/layout/hexagon-enum.stderr b/tests/ui/layout/hexagon-enum.stderr index 96f0a8c87408..90c06ba1f834 100644 --- a/tests/ui/layout/hexagon-enum.stderr +++ b/tests/ui/layout/hexagon-enum.stderr @@ -31,6 +31,7 @@ error: layout_of(A) = Layout { valid_range: 0..=0, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -56,6 +57,7 @@ error: layout_of(A) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -107,6 +109,7 @@ error: layout_of(B) = Layout { valid_range: 255..=255, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -132,6 +135,7 @@ error: layout_of(B) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -183,6 +187,7 @@ error: layout_of(C) = Layout { valid_range: 256..=256, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -208,6 +213,7 @@ error: layout_of(C) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -259,6 +265,7 @@ error: layout_of(P) = Layout { valid_range: 268435456..=268435456, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -284,6 +291,7 @@ error: layout_of(P) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -335,6 +343,7 @@ error: layout_of(T) = Layout { valid_range: 2164260864..=2164260864, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -360,6 +369,7 @@ error: layout_of(T) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, diff --git a/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr b/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr index cd9e4c027815..3bdb9c5c143e 100644 --- a/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr +++ b/tests/ui/layout/issue-96158-scalarpair-payload-might-be-uninit.stderr @@ -37,6 +37,7 @@ error: layout_of(MissingPayloadField) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -78,6 +79,7 @@ error: layout_of(MissingPayloadField) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -99,6 +101,7 @@ error: layout_of(MissingPayloadField) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, @@ -157,6 +160,7 @@ error: layout_of(CommonPayloadField) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -199,6 +203,7 @@ error: layout_of(CommonPayloadField) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -237,6 +242,7 @@ error: layout_of(CommonPayloadField) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, @@ -294,6 +300,7 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -335,6 +342,7 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -372,6 +380,7 @@ error: layout_of(CommonPayloadFieldIsMaybeUninit) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, @@ -429,6 +438,7 @@ error: layout_of(NicheFirst) = Layout { valid_range: 0..=4, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -486,6 +496,7 @@ error: layout_of(NicheFirst) = Layout { valid_range: 0..=2, }, ), + uninhabited: false, variants: Single { index: 0, }, @@ -507,6 +518,7 @@ error: layout_of(NicheFirst) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, @@ -528,6 +540,7 @@ error: layout_of(NicheFirst) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 2, }, @@ -585,6 +598,7 @@ error: layout_of(NicheSecond) = Layout { valid_range: 0..=4, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -642,6 +656,7 @@ error: layout_of(NicheSecond) = Layout { valid_range: 0..=2, }, ), + uninhabited: false, variants: Single { index: 0, }, @@ -663,6 +678,7 @@ error: layout_of(NicheSecond) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, @@ -684,6 +700,7 @@ error: layout_of(NicheSecond) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 2, }, diff --git a/tests/ui/layout/issue-96185-overaligned-enum.stderr b/tests/ui/layout/issue-96185-overaligned-enum.stderr index 15a3f6004f50..1d4e44364482 100644 --- a/tests/ui/layout/issue-96185-overaligned-enum.stderr +++ b/tests/ui/layout/issue-96185-overaligned-enum.stderr @@ -25,6 +25,7 @@ error: layout_of(Aligned1) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -50,6 +51,7 @@ error: layout_of(Aligned1) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -73,6 +75,7 @@ error: layout_of(Aligned1) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, @@ -128,6 +131,7 @@ error: layout_of(Aligned2) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -153,6 +157,7 @@ error: layout_of(Aligned2) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -176,6 +181,7 @@ error: layout_of(Aligned2) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, diff --git a/tests/ui/layout/thumb-enum.stderr b/tests/ui/layout/thumb-enum.stderr index 120081d193c6..0c3433185647 100644 --- a/tests/ui/layout/thumb-enum.stderr +++ b/tests/ui/layout/thumb-enum.stderr @@ -31,6 +31,7 @@ error: layout_of(A) = Layout { valid_range: 0..=0, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -56,6 +57,7 @@ error: layout_of(A) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -107,6 +109,7 @@ error: layout_of(B) = Layout { valid_range: 255..=255, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -132,6 +135,7 @@ error: layout_of(B) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -183,6 +187,7 @@ error: layout_of(C) = Layout { valid_range: 256..=256, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -208,6 +213,7 @@ error: layout_of(C) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -259,6 +265,7 @@ error: layout_of(P) = Layout { valid_range: 268435456..=268435456, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -284,6 +291,7 @@ error: layout_of(P) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -335,6 +343,7 @@ error: layout_of(T) = Layout { valid_range: 2164260864..=2164260864, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -360,6 +369,7 @@ error: layout_of(T) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, diff --git a/tests/ui/layout/zero-sized-array-enum-niche.stderr b/tests/ui/layout/zero-sized-array-enum-niche.stderr index b6fcc14c063c..33d2eede2209 100644 --- a/tests/ui/layout/zero-sized-array-enum-niche.stderr +++ b/tests/ui/layout/zero-sized-array-enum-niche.stderr @@ -25,6 +25,7 @@ error: layout_of(Result<[u32; 0], bool>) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -54,6 +55,7 @@ error: layout_of(Result<[u32; 0], bool>) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -88,6 +90,7 @@ error: layout_of(Result<[u32; 0], bool>) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Single { index: 1, }, @@ -133,6 +136,7 @@ error: layout_of(MultipleAlignments) = Layout { valid_range: 0..=2, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -162,6 +166,7 @@ error: layout_of(MultipleAlignments) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -187,6 +192,7 @@ error: layout_of(MultipleAlignments) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, @@ -221,6 +227,7 @@ error: layout_of(MultipleAlignments) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Single { index: 2, }, @@ -266,6 +273,7 @@ error: layout_of(Result<[u32; 0], Packed>>) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -295,6 +303,7 @@ error: layout_of(Result<[u32; 0], Packed>>) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -329,6 +338,7 @@ error: layout_of(Result<[u32; 0], Packed>>) = Layout { valid_range: 1..=65535, }, ), + uninhabited: false, variants: Single { index: 1, }, @@ -374,6 +384,7 @@ error: layout_of(Result<[u32; 0], Packed>) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -407,6 +418,7 @@ error: layout_of(Result<[u32; 0], Packed>) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -441,6 +453,7 @@ error: layout_of(Result<[u32; 0], Packed>) = Layout { valid_range: 0..=0, }, ), + uninhabited: false, variants: Single { index: 1, }, diff --git a/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr b/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr index 8e8f1d159b74..204db30786ee 100644 --- a/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr +++ b/tests/ui/repr/repr-c-dead-variants.aarch64-unknown-linux-gnu.stderr @@ -4,7 +4,15 @@ error: layout_of(Univariant) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: Scalar( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 0..=0, + }, + ), fields: Arbitrary { offsets: [ Size(0 bytes), @@ -23,6 +31,7 @@ error: layout_of(Univariant) = Layout { valid_range: 0..=0, }, ), + uninhabited: true, variants: Multiple { tag: Initialized { value: Int( @@ -40,7 +49,15 @@ error: layout_of(Univariant) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: Scalar( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 0..=0, + }, + ), fields: Arbitrary { offsets: [ Size(4 bytes), @@ -50,6 +67,7 @@ error: layout_of(Univariant) = Layout { ], }, largest_niche: None, + uninhabited: true, variants: Single { index: 0, }, @@ -107,6 +125,7 @@ error: layout_of(TwoVariants) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -119,12 +138,26 @@ error: layout_of(TwoVariants) = Layout { tag_field: 0, variants: [ Layout { - size: Size(4 bytes), + size: Size(8 bytes), align: AbiAndPrefAlign { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: ScalarPair( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 0..=1, + }, + Union { + value: Int( + I8, + false, + ), + }, + ), fields: Arbitrary { offsets: [ Size(4 bytes), @@ -134,6 +167,7 @@ error: layout_of(TwoVariants) = Layout { ], }, largest_niche: None, + uninhabited: true, variants: Single { index: 0, }, @@ -171,6 +205,7 @@ error: layout_of(TwoVariants) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, @@ -216,6 +251,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -233,7 +269,9 @@ error: layout_of(DeadBranchHasOtherField) = Layout { abi: Align(8 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: Memory { + sized: true, + }, fields: Arbitrary { offsets: [ Size(8 bytes), @@ -245,6 +283,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { ], }, largest_niche: None, + uninhabited: true, variants: Single { index: 0, }, @@ -272,6 +311,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, diff --git a/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr b/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr index 2cd0960ce3ee..1fab00bf50c4 100644 --- a/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr +++ b/tests/ui/repr/repr-c-dead-variants.armebv7r-none-eabi.stderr @@ -4,7 +4,15 @@ error: layout_of(Univariant) = Layout { abi: Align(1 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: Scalar( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=0, + }, + ), fields: Arbitrary { offsets: [ Size(0 bytes), @@ -23,6 +31,7 @@ error: layout_of(Univariant) = Layout { valid_range: 0..=0, }, ), + uninhabited: true, variants: Multiple { tag: Initialized { value: Int( @@ -40,7 +49,15 @@ error: layout_of(Univariant) = Layout { abi: Align(1 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: Scalar( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=0, + }, + ), fields: Arbitrary { offsets: [ Size(1 bytes), @@ -50,6 +67,7 @@ error: layout_of(Univariant) = Layout { ], }, largest_niche: None, + uninhabited: true, variants: Single { index: 0, }, @@ -107,6 +125,7 @@ error: layout_of(TwoVariants) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -119,12 +138,26 @@ error: layout_of(TwoVariants) = Layout { tag_field: 0, variants: [ Layout { - size: Size(1 bytes), + size: Size(2 bytes), align: AbiAndPrefAlign { abi: Align(1 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: ScalarPair( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + Union { + value: Int( + I8, + false, + ), + }, + ), fields: Arbitrary { offsets: [ Size(1 bytes), @@ -134,6 +167,7 @@ error: layout_of(TwoVariants) = Layout { ], }, largest_niche: None, + uninhabited: true, variants: Single { index: 0, }, @@ -171,6 +205,7 @@ error: layout_of(TwoVariants) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, @@ -216,6 +251,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -233,7 +269,9 @@ error: layout_of(DeadBranchHasOtherField) = Layout { abi: Align(8 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: Memory { + sized: true, + }, fields: Arbitrary { offsets: [ Size(8 bytes), @@ -245,6 +283,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { ], }, largest_niche: None, + uninhabited: true, variants: Single { index: 0, }, @@ -272,6 +311,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, diff --git a/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr b/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr index 8e8f1d159b74..204db30786ee 100644 --- a/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr +++ b/tests/ui/repr/repr-c-dead-variants.i686-pc-windows-msvc.stderr @@ -4,7 +4,15 @@ error: layout_of(Univariant) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: Scalar( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 0..=0, + }, + ), fields: Arbitrary { offsets: [ Size(0 bytes), @@ -23,6 +31,7 @@ error: layout_of(Univariant) = Layout { valid_range: 0..=0, }, ), + uninhabited: true, variants: Multiple { tag: Initialized { value: Int( @@ -40,7 +49,15 @@ error: layout_of(Univariant) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: Scalar( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 0..=0, + }, + ), fields: Arbitrary { offsets: [ Size(4 bytes), @@ -50,6 +67,7 @@ error: layout_of(Univariant) = Layout { ], }, largest_niche: None, + uninhabited: true, variants: Single { index: 0, }, @@ -107,6 +125,7 @@ error: layout_of(TwoVariants) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -119,12 +138,26 @@ error: layout_of(TwoVariants) = Layout { tag_field: 0, variants: [ Layout { - size: Size(4 bytes), + size: Size(8 bytes), align: AbiAndPrefAlign { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: ScalarPair( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 0..=1, + }, + Union { + value: Int( + I8, + false, + ), + }, + ), fields: Arbitrary { offsets: [ Size(4 bytes), @@ -134,6 +167,7 @@ error: layout_of(TwoVariants) = Layout { ], }, largest_niche: None, + uninhabited: true, variants: Single { index: 0, }, @@ -171,6 +205,7 @@ error: layout_of(TwoVariants) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, @@ -216,6 +251,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -233,7 +269,9 @@ error: layout_of(DeadBranchHasOtherField) = Layout { abi: Align(8 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: Memory { + sized: true, + }, fields: Arbitrary { offsets: [ Size(8 bytes), @@ -245,6 +283,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { ], }, largest_niche: None, + uninhabited: true, variants: Single { index: 0, }, @@ -272,6 +311,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, diff --git a/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr b/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr index 8e8f1d159b74..204db30786ee 100644 --- a/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr +++ b/tests/ui/repr/repr-c-dead-variants.x86_64-unknown-linux-gnu.stderr @@ -4,7 +4,15 @@ error: layout_of(Univariant) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: Scalar( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 0..=0, + }, + ), fields: Arbitrary { offsets: [ Size(0 bytes), @@ -23,6 +31,7 @@ error: layout_of(Univariant) = Layout { valid_range: 0..=0, }, ), + uninhabited: true, variants: Multiple { tag: Initialized { value: Int( @@ -40,7 +49,15 @@ error: layout_of(Univariant) = Layout { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: Scalar( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 0..=0, + }, + ), fields: Arbitrary { offsets: [ Size(4 bytes), @@ -50,6 +67,7 @@ error: layout_of(Univariant) = Layout { ], }, largest_niche: None, + uninhabited: true, variants: Single { index: 0, }, @@ -107,6 +125,7 @@ error: layout_of(TwoVariants) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -119,12 +138,26 @@ error: layout_of(TwoVariants) = Layout { tag_field: 0, variants: [ Layout { - size: Size(4 bytes), + size: Size(8 bytes), align: AbiAndPrefAlign { abi: Align(4 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: ScalarPair( + Initialized { + value: Int( + I32, + false, + ), + valid_range: 0..=1, + }, + Union { + value: Int( + I8, + false, + ), + }, + ), fields: Arbitrary { offsets: [ Size(4 bytes), @@ -134,6 +167,7 @@ error: layout_of(TwoVariants) = Layout { ], }, largest_niche: None, + uninhabited: true, variants: Single { index: 0, }, @@ -171,6 +205,7 @@ error: layout_of(TwoVariants) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, @@ -216,6 +251,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -233,7 +269,9 @@ error: layout_of(DeadBranchHasOtherField) = Layout { abi: Align(8 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: Memory { + sized: true, + }, fields: Arbitrary { offsets: [ Size(8 bytes), @@ -245,6 +283,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { ], }, largest_niche: None, + uninhabited: true, variants: Single { index: 0, }, @@ -272,6 +311,7 @@ error: layout_of(DeadBranchHasOtherField) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, diff --git a/tests/ui/repr/repr-c-int-dead-variants.stderr b/tests/ui/repr/repr-c-int-dead-variants.stderr index fa08b323dec2..f852212deb90 100644 --- a/tests/ui/repr/repr-c-int-dead-variants.stderr +++ b/tests/ui/repr/repr-c-int-dead-variants.stderr @@ -4,7 +4,15 @@ error: layout_of(UnivariantU8) = Layout { abi: Align(1 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: Scalar( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=0, + }, + ), fields: Arbitrary { offsets: [ Size(0 bytes), @@ -23,6 +31,7 @@ error: layout_of(UnivariantU8) = Layout { valid_range: 0..=0, }, ), + uninhabited: true, variants: Multiple { tag: Initialized { value: Int( @@ -40,7 +49,15 @@ error: layout_of(UnivariantU8) = Layout { abi: Align(1 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: Scalar( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=0, + }, + ), fields: Arbitrary { offsets: [ Size(1 bytes), @@ -50,6 +67,7 @@ error: layout_of(UnivariantU8) = Layout { ], }, largest_niche: None, + uninhabited: true, variants: Single { index: 0, }, @@ -107,6 +125,7 @@ error: layout_of(TwoVariantsU8) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -119,12 +138,26 @@ error: layout_of(TwoVariantsU8) = Layout { tag_field: 0, variants: [ Layout { - size: Size(1 bytes), + size: Size(2 bytes), align: AbiAndPrefAlign { abi: Align(1 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: ScalarPair( + Initialized { + value: Int( + I8, + false, + ), + valid_range: 0..=1, + }, + Union { + value: Int( + I8, + false, + ), + }, + ), fields: Arbitrary { offsets: [ Size(1 bytes), @@ -134,6 +167,7 @@ error: layout_of(TwoVariantsU8) = Layout { ], }, largest_niche: None, + uninhabited: true, variants: Single { index: 0, }, @@ -171,6 +205,7 @@ error: layout_of(TwoVariantsU8) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, @@ -216,6 +251,7 @@ error: layout_of(DeadBranchHasOtherFieldU8) = Layout { valid_range: 0..=1, }, ), + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -233,7 +269,9 @@ error: layout_of(DeadBranchHasOtherFieldU8) = Layout { abi: Align(8 bytes), pref: $SOME_ALIGN, }, - abi: Uninhabited, + abi: Memory { + sized: true, + }, fields: Arbitrary { offsets: [ Size(8 bytes), @@ -245,6 +283,7 @@ error: layout_of(DeadBranchHasOtherFieldU8) = Layout { ], }, largest_niche: None, + uninhabited: true, variants: Single { index: 0, }, @@ -272,6 +311,7 @@ error: layout_of(DeadBranchHasOtherFieldU8) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Single { index: 1, }, diff --git a/tests/ui/resolve/dot-notation-type-namespace-suggest-path-sep.rs b/tests/ui/resolve/dot-notation-type-namespace-suggest-path-sep.rs new file mode 100644 index 000000000000..432e3c0b77ef --- /dev/null +++ b/tests/ui/resolve/dot-notation-type-namespace-suggest-path-sep.rs @@ -0,0 +1,123 @@ +// see also https://github.com/rust-lang/rust/issues/22692 + +type Alias = Vec; + +mod foo { + fn bar() {} +} + +fn main() { + let _ = String.new(); + //~^ ERROR expected value, found struct `String` + //~| HELP use the path separator + + let _ = String.default; + //~^ ERROR expected value, found struct `String` + //~| HELP use the path separator + + let _ = Vec::<()>.with_capacity(1); + //~^ ERROR expected value, found struct `Vec` + //~| HELP use the path separator + + let _ = Alias.new(); + //~^ ERROR expected value, found type alias `Alias` + //~| HELP use the path separator + + let _ = Alias.default; + //~^ ERROR expected value, found type alias `Alias` + //~| HELP use the path separator + + let _ = foo.bar; + //~^ ERROR expected value, found module `foo` + //~| HELP use the path separator +} + +macro_rules! Type { + () => { + ::std::cell::Cell + //~^ ERROR expected value, found struct `std::cell::Cell` + //~| ERROR expected value, found struct `std::cell::Cell` + //~| ERROR expected value, found struct `std::cell::Cell` + }; + (alias) => { + Alias + //~^ ERROR expected value, found type alias `Alias` + //~| ERROR expected value, found type alias `Alias` + //~| ERROR expected value, found type alias `Alias` + }; +} + +macro_rules! create { + (type method) => { + Vec.new() + //~^ ERROR expected value, found struct `Vec` + //~| HELP use the path separator + }; + (type field) => { + Vec.new + //~^ ERROR expected value, found struct `Vec` + //~| HELP use the path separator + }; + (macro method) => { + Type!().new(0) + //~^ HELP use the path separator + }; + (macro method alias) => { + Type!(alias).new(0) + //~^ HELP use the path separator + }; +} + +macro_rules! check_ty { + ($Ty:ident) => { + $Ty.foo + //~^ ERROR expected value, found type alias `Alias` + //~| HELP use the path separator + }; +} +macro_rules! check_ident { + ($Ident:ident) => { + Alias.$Ident + //~^ ERROR expected value, found type alias `Alias` + //~| HELP use the path separator + }; +} +macro_rules! check_ty_ident { + ($Ty:ident, $Ident:ident) => { + $Ty.$Ident + //~^ ERROR expected value, found type alias `Alias` + //~| HELP use the path separator + }; +} + +fn interaction_with_macros() { + // + // Verify that we do not only suggest to replace `.` with `::` if the receiver is a + // macro call but that we also correctly suggest to surround it with angle brackets. + // + + Type!().get(); + //~^ HELP use the path separator + + Type! {}.get; + //~^ HELP use the path separator + + Type!(alias).get(); + //~^ HELP use the path separator + + Type! {alias}.get; + //~^ HELP use the path separator + + // + // Ensure that the suggestion is shown for expressions inside of macro definitions. + // + + let _ = create!(type method); + let _ = create!(type field); + let _ = create!(macro method); + let _ = create!(macro method alias); + + let _ = check_ty!(Alias); + let _ = check_ident!(foo); + let _ = check_ty_ident!(Alias, foo); +} diff --git a/tests/ui/resolve/dot-notation-type-namespace-suggest-path-sep.stderr b/tests/ui/resolve/dot-notation-type-namespace-suggest-path-sep.stderr new file mode 100644 index 000000000000..d74814dd876c --- /dev/null +++ b/tests/ui/resolve/dot-notation-type-namespace-suggest-path-sep.stderr @@ -0,0 +1,251 @@ +error[E0423]: expected value, found struct `String` + --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:10:13 + | +LL | let _ = String.new(); + | ^^^^^^ + | +help: use the path separator to refer to an item + | +LL - let _ = String.new(); +LL + let _ = String::new(); + | + +error[E0423]: expected value, found struct `String` + --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:14:13 + | +LL | let _ = String.default; + | ^^^^^^ + | +help: use the path separator to refer to an item + | +LL - let _ = String.default; +LL + let _ = String::default; + | + +error[E0423]: expected value, found struct `Vec` + --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:18:13 + | +LL | let _ = Vec::<()>.with_capacity(1); + | ^^^^^^^^^ + | +help: use the path separator to refer to an item + | +LL - let _ = Vec::<()>.with_capacity(1); +LL + let _ = Vec::<()>::with_capacity(1); + | + +error[E0423]: expected value, found type alias `Alias` + --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:22:13 + | +LL | let _ = Alias.new(); + | ^^^^^ + | +help: use the path separator to refer to an item + | +LL - let _ = Alias.new(); +LL + let _ = Alias::new(); + | + +error[E0423]: expected value, found type alias `Alias` + --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:26:13 + | +LL | let _ = Alias.default; + | ^^^^^ + | +help: use the path separator to refer to an item + | +LL - let _ = Alias.default; +LL + let _ = Alias::default; + | + +error[E0423]: expected value, found module `foo` + --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:30:13 + | +LL | let _ = foo.bar; + | ^^^ + | +help: use the path separator to refer to an item + | +LL - let _ = foo.bar; +LL + let _ = foo::bar; + | + +error[E0423]: expected value, found struct `std::cell::Cell` + --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:37:9 + | +LL | ::std::cell::Cell + | ^^^^^^^^^^^^^^^^^ +... +LL | Type!().get(); + | ------- in this macro invocation + | + = note: this error originates in the macro `Type` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use the path separator to refer to an item + | +LL - Type!().get(); +LL + ::get(); + | + +error[E0423]: expected value, found struct `std::cell::Cell` + --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:37:9 + | +LL | ::std::cell::Cell + | ^^^^^^^^^^^^^^^^^ +... +LL | Type! {}.get; + | -------- in this macro invocation + | + = note: this error originates in the macro `Type` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use the path separator to refer to an item + | +LL - Type! {}.get; +LL + ::get; + | + +error[E0423]: expected value, found type alias `Alias` + --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:43:9 + | +LL | Alias + | ^^^^^ +... +LL | Type!(alias).get(); + | ------------ in this macro invocation + | + = note: this error originates in the macro `Type` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use the path separator to refer to an item + | +LL - Type!(alias).get(); +LL + ::get(); + | + +error[E0423]: expected value, found type alias `Alias` + --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:43:9 + | +LL | Alias + | ^^^^^ +... +LL | Type! {alias}.get; + | ------------- in this macro invocation + | + = note: this error originates in the macro `Type` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use the path separator to refer to an item + | +LL - Type! {alias}.get; +LL + ::get; + | + +error[E0423]: expected value, found struct `Vec` + --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:52:9 + | +LL | Vec.new() + | ^^^ +... +LL | let _ = create!(type method); + | -------------------- in this macro invocation + | + = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use the path separator to refer to an item + | +LL - Vec.new() +LL + Vec::new() + | + +error[E0423]: expected value, found struct `Vec` + --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:57:9 + | +LL | Vec.new + | ^^^ +... +LL | let _ = create!(type field); + | ------------------- in this macro invocation + | + = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use the path separator to refer to an item + | +LL - Vec.new +LL + Vec::new + | + +error[E0423]: expected value, found struct `std::cell::Cell` + --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:37:9 + | +LL | ::std::cell::Cell + | ^^^^^^^^^^^^^^^^^ +... +LL | let _ = create!(macro method); + | --------------------- in this macro invocation + | + = note: this error originates in the macro `Type` which comes from the expansion of the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use the path separator to refer to an item + | +LL - Type!().new(0) +LL + ::new(0) + | + +error[E0423]: expected value, found type alias `Alias` + --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:43:9 + | +LL | Alias + | ^^^^^ +... +LL | let _ = create!(macro method alias); + | --------------------------- in this macro invocation + | + = note: this error originates in the macro `Type` which comes from the expansion of the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use the path separator to refer to an item + | +LL - Type!(alias).new(0) +LL + ::new(0) + | + +error[E0423]: expected value, found type alias `Alias` + --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:73:9 + | +LL | $Ty.foo + | ^^^ +... +LL | let _ = check_ty!(Alias); + | ---------------- in this macro invocation + | + = note: this error originates in the macro `check_ty` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use the path separator to refer to an item + | +LL - $Ty.foo +LL + $Ty::foo + | + +error[E0423]: expected value, found type alias `Alias` + --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:80:9 + | +LL | Alias.$Ident + | ^^^^^ +... +LL | let _ = check_ident!(foo); + | ----------------- in this macro invocation + | + = note: this error originates in the macro `check_ident` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use the path separator to refer to an item + | +LL - Alias.$Ident +LL + ::$Ident + | + +error[E0423]: expected value, found type alias `Alias` + --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:87:9 + | +LL | $Ty.$Ident + | ^^^ +... +LL | let _ = check_ty_ident!(Alias, foo); + | --------------------------- in this macro invocation + | + = note: this error originates in the macro `check_ty_ident` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use the path separator to refer to an item + | +LL - $Ty.$Ident +LL + <$Ty>::$Ident + | + +error: aborting due to 17 previous errors + +For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/resolve/enum-expected-value-suggest-variants.rs b/tests/ui/resolve/enum-expected-value-suggest-variants.rs new file mode 100644 index 000000000000..9f86a0a1ecc7 --- /dev/null +++ b/tests/ui/resolve/enum-expected-value-suggest-variants.rs @@ -0,0 +1,58 @@ +enum Foo { + //~^ HELP consider importing this tuple variant + A(u32), + B(u32), +} + +enum Bar { + C(u32), + D(u32), + E, + F, +} + +fn main() { + let _: Foo = Foo(0); + //~^ ERROR expected function + //~| HELP try to construct one of the enum's variants + + let _: Foo = Foo.A(0); + //~^ ERROR expected value, found enum `Foo` + //~| HELP use the path separator to refer to a variant + + let _: Foo = Foo.Bad(0); + //~^ ERROR expected value, found enum `Foo` + //~| HELP the following enum variants are available + + let _: Bar = Bar(0); + //~^ ERROR expected function + //~| HELP try to construct one of the enum's variants + //~| HELP you might have meant to construct one of the enum's non-tuple variants + + let _: Bar = Bar.C(0); + //~^ ERROR expected value, found enum `Bar` + //~| HELP use the path separator to refer to a variant + + let _: Bar = Bar.E; + //~^ ERROR expected value, found enum `Bar` + //~| HELP use the path separator to refer to a variant + + let _: Bar = Bar.Bad(0); + //~^ ERROR expected value, found enum `Bar` + //~| HELP you might have meant to use one of the following enum variants + //~| HELP alternatively, the following enum variants are also available + + let _: Bar = Bar.Bad; + //~^ ERROR expected value, found enum `Bar` + //~| HELP you might have meant to use one of the following enum variants + //~| HELP alternatively, the following enum variants are also available + + match Foo::A(42) { + A(..) => {} + //~^ ERROR cannot find tuple struct or tuple variant `A` in this scope + Foo(..) => {} + //~^ ERROR expected tuple struct or tuple variant + //~| HELP try to match against one of the enum's variants + _ => {} + } +} diff --git a/tests/ui/resolve/enum-expected-value-suggest-variants.stderr b/tests/ui/resolve/enum-expected-value-suggest-variants.stderr new file mode 100644 index 000000000000..f99aea0493a5 --- /dev/null +++ b/tests/ui/resolve/enum-expected-value-suggest-variants.stderr @@ -0,0 +1,244 @@ +error[E0423]: expected value, found enum `Foo` + --> $DIR/enum-expected-value-suggest-variants.rs:19:18 + | +LL | let _: Foo = Foo.A(0); + | ^^^ + | +note: the enum is defined here + --> $DIR/enum-expected-value-suggest-variants.rs:1:1 + | +LL | / enum Foo { +LL | | +LL | | A(u32), +LL | | B(u32), +LL | | } + | |_^ +help: use the path separator to refer to a variant + | +LL - let _: Foo = Foo.A(0); +LL + let _: Foo = Foo::A(0); + | + +error[E0423]: expected value, found enum `Foo` + --> $DIR/enum-expected-value-suggest-variants.rs:23:18 + | +LL | let _: Foo = Foo.Bad(0); + | ^^^ + | +note: the enum is defined here + --> $DIR/enum-expected-value-suggest-variants.rs:1:1 + | +LL | / enum Foo { +LL | | +LL | | A(u32), +LL | | B(u32), +LL | | } + | |_^ +help: the following enum variants are available + | +LL - let _: Foo = Foo.Bad(0); +LL + let _: Foo = (Foo::A(/* fields */)).Bad(0); + | +LL - let _: Foo = Foo.Bad(0); +LL + let _: Foo = (Foo::B(/* fields */)).Bad(0); + | + +error[E0423]: expected value, found enum `Bar` + --> $DIR/enum-expected-value-suggest-variants.rs:32:18 + | +LL | let _: Bar = Bar.C(0); + | ^^^ + | +note: the enum is defined here + --> $DIR/enum-expected-value-suggest-variants.rs:7:1 + | +LL | / enum Bar { +LL | | C(u32), +LL | | D(u32), +LL | | E, +LL | | F, +LL | | } + | |_^ +help: use the path separator to refer to a variant + | +LL - let _: Bar = Bar.C(0); +LL + let _: Bar = Bar::C(0); + | + +error[E0423]: expected value, found enum `Bar` + --> $DIR/enum-expected-value-suggest-variants.rs:36:18 + | +LL | let _: Bar = Bar.E; + | ^^^ + | +note: the enum is defined here + --> $DIR/enum-expected-value-suggest-variants.rs:7:1 + | +LL | / enum Bar { +LL | | C(u32), +LL | | D(u32), +LL | | E, +LL | | F, +LL | | } + | |_^ +help: use the path separator to refer to a variant + | +LL - let _: Bar = Bar.E; +LL + let _: Bar = Bar::E; + | + +error[E0423]: expected value, found enum `Bar` + --> $DIR/enum-expected-value-suggest-variants.rs:40:18 + | +LL | let _: Bar = Bar.Bad(0); + | ^^^ + | +note: the enum is defined here + --> $DIR/enum-expected-value-suggest-variants.rs:7:1 + | +LL | / enum Bar { +LL | | C(u32), +LL | | D(u32), +LL | | E, +LL | | F, +LL | | } + | |_^ +help: you might have meant to use one of the following enum variants + | +LL - let _: Bar = Bar.Bad(0); +LL + let _: Bar = Bar::E.Bad(0); + | +LL - let _: Bar = Bar.Bad(0); +LL + let _: Bar = Bar::F.Bad(0); + | +help: alternatively, the following enum variants are also available + | +LL - let _: Bar = Bar.Bad(0); +LL + let _: Bar = (Bar::C(/* fields */)).Bad(0); + | +LL - let _: Bar = Bar.Bad(0); +LL + let _: Bar = (Bar::D(/* fields */)).Bad(0); + | + +error[E0423]: expected value, found enum `Bar` + --> $DIR/enum-expected-value-suggest-variants.rs:45:18 + | +LL | let _: Bar = Bar.Bad; + | ^^^ + | +note: the enum is defined here + --> $DIR/enum-expected-value-suggest-variants.rs:7:1 + | +LL | / enum Bar { +LL | | C(u32), +LL | | D(u32), +LL | | E, +LL | | F, +LL | | } + | |_^ +help: you might have meant to use one of the following enum variants + | +LL - let _: Bar = Bar.Bad; +LL + let _: Bar = Bar::E.Bad; + | +LL - let _: Bar = Bar.Bad; +LL + let _: Bar = Bar::F.Bad; + | +help: alternatively, the following enum variants are also available + | +LL - let _: Bar = Bar.Bad; +LL + let _: Bar = (Bar::C(/* fields */)).Bad; + | +LL - let _: Bar = Bar.Bad; +LL + let _: Bar = (Bar::D(/* fields */)).Bad; + | + +error[E0531]: cannot find tuple struct or tuple variant `A` in this scope + --> $DIR/enum-expected-value-suggest-variants.rs:51:9 + | +LL | A(..) => {} + | ^ not found in this scope + | +help: consider importing this tuple variant + | +LL + use Foo::A; + | + +error[E0532]: expected tuple struct or tuple variant, found enum `Foo` + --> $DIR/enum-expected-value-suggest-variants.rs:53:9 + | +LL | Foo(..) => {} + | ^^^ + | +note: the enum is defined here + --> $DIR/enum-expected-value-suggest-variants.rs:1:1 + | +LL | / enum Foo { +LL | | +LL | | A(u32), +LL | | B(u32), +LL | | } + | |_^ +help: try to match against one of the enum's variants + | +LL - Foo(..) => {} +LL + Foo::A(..) => {} + | +LL - Foo(..) => {} +LL + Foo::B(..) => {} + | + +error[E0423]: expected function, tuple struct or tuple variant, found enum `Foo` + --> $DIR/enum-expected-value-suggest-variants.rs:15:18 + | +LL | let _: Foo = Foo(0); + | ^^^ + | +note: the enum is defined here + --> $DIR/enum-expected-value-suggest-variants.rs:1:1 + | +LL | / enum Foo { +LL | | +LL | | A(u32), +LL | | B(u32), +LL | | } + | |_^ +help: try to construct one of the enum's variants + | +LL - let _: Foo = Foo(0); +LL + let _: Foo = Foo::A(0); + | +LL - let _: Foo = Foo(0); +LL + let _: Foo = Foo::B(0); + | + +error[E0423]: expected function, tuple struct or tuple variant, found enum `Bar` + --> $DIR/enum-expected-value-suggest-variants.rs:27:18 + | +LL | let _: Bar = Bar(0); + | ^^^ + | + = help: you might have meant to construct one of the enum's non-tuple variants +note: the enum is defined here + --> $DIR/enum-expected-value-suggest-variants.rs:7:1 + | +LL | / enum Bar { +LL | | C(u32), +LL | | D(u32), +LL | | E, +LL | | F, +LL | | } + | |_^ +help: try to construct one of the enum's variants + | +LL - let _: Bar = Bar(0); +LL + let _: Bar = Bar::C(0); + | +LL - let _: Bar = Bar(0); +LL + let _: Bar = Bar::D(0); + | + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0423, E0531, E0532. +For more information about an error, try `rustc --explain E0423`. diff --git a/tests/ui/resolve/issue-22692.rs b/tests/ui/resolve/issue-22692.rs deleted file mode 100644 index 31a76261408e..000000000000 --- a/tests/ui/resolve/issue-22692.rs +++ /dev/null @@ -1,60 +0,0 @@ -fn main() { - let _ = String.new(); - //~^ ERROR expected value, found struct `String` - //~| HELP use the path separator - - let _ = String.default; - //~^ ERROR expected value, found struct `String` - //~| HELP use the path separator - - let _ = Vec::<()>.with_capacity(1); - //~^ ERROR expected value, found struct `Vec` - //~| HELP use the path separator -} - -macro_rules! Type { - () => { - ::std::cell::Cell - //~^ ERROR expected value, found struct `std::cell::Cell` - //~| ERROR expected value, found struct `std::cell::Cell` - //~| ERROR expected value, found struct `std::cell::Cell` - }; -} - -macro_rules! create { - (type method) => { - Vec.new() - //~^ ERROR expected value, found struct `Vec` - //~| HELP use the path separator - }; - (type field) => { - Vec.new - //~^ ERROR expected value, found struct `Vec` - //~| HELP use the path separator - }; - (macro method) => { - Type!().new(0) - //~^ HELP use the path separator - }; -} - -fn interaction_with_macros() { - // - // Verify that we do not only suggest to replace `.` with `::` if the receiver is a - // macro call but that we also correctly suggest to surround it with angle brackets. - // - - Type!().get(); - //~^ HELP use the path separator - - Type! {}.get; - //~^ HELP use the path separator - - // - // Ensure that the suggestion is shown for expressions inside of macro definitions. - // - - let _ = create!(type method); - let _ = create!(type field); - let _ = create!(macro method); -} diff --git a/tests/ui/resolve/issue-22692.stderr b/tests/ui/resolve/issue-22692.stderr deleted file mode 100644 index 546f12b35c15..000000000000 --- a/tests/ui/resolve/issue-22692.stderr +++ /dev/null @@ -1,119 +0,0 @@ -error[E0423]: expected value, found struct `String` - --> $DIR/issue-22692.rs:2:13 - | -LL | let _ = String.new(); - | ^^^^^^ - | -help: use the path separator to refer to an item - | -LL - let _ = String.new(); -LL + let _ = String::new(); - | - -error[E0423]: expected value, found struct `String` - --> $DIR/issue-22692.rs:6:13 - | -LL | let _ = String.default; - | ^^^^^^ - | -help: use the path separator to refer to an item - | -LL - let _ = String.default; -LL + let _ = String::default; - | - -error[E0423]: expected value, found struct `Vec` - --> $DIR/issue-22692.rs:10:13 - | -LL | let _ = Vec::<()>.with_capacity(1); - | ^^^^^^^^^ - | -help: use the path separator to refer to an item - | -LL - let _ = Vec::<()>.with_capacity(1); -LL + let _ = Vec::<()>::with_capacity(1); - | - -error[E0423]: expected value, found struct `std::cell::Cell` - --> $DIR/issue-22692.rs:17:9 - | -LL | ::std::cell::Cell - | ^^^^^^^^^^^^^^^^^ -... -LL | Type!().get(); - | ------- in this macro invocation - | - = note: this error originates in the macro `Type` (in Nightly builds, run with -Z macro-backtrace for more info) -help: use the path separator to refer to an item - | -LL - Type!().get(); -LL + ::get(); - | - -error[E0423]: expected value, found struct `std::cell::Cell` - --> $DIR/issue-22692.rs:17:9 - | -LL | ::std::cell::Cell - | ^^^^^^^^^^^^^^^^^ -... -LL | Type! {}.get; - | -------- in this macro invocation - | - = note: this error originates in the macro `Type` (in Nightly builds, run with -Z macro-backtrace for more info) -help: use the path separator to refer to an item - | -LL - Type! {}.get; -LL + ::get; - | - -error[E0423]: expected value, found struct `Vec` - --> $DIR/issue-22692.rs:26:9 - | -LL | Vec.new() - | ^^^ -... -LL | let _ = create!(type method); - | -------------------- in this macro invocation - | - = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) -help: use the path separator to refer to an item - | -LL - Vec.new() -LL + Vec::new() - | - -error[E0423]: expected value, found struct `Vec` - --> $DIR/issue-22692.rs:31:9 - | -LL | Vec.new - | ^^^ -... -LL | let _ = create!(type field); - | ------------------- in this macro invocation - | - = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) -help: use the path separator to refer to an item - | -LL - Vec.new -LL + Vec::new - | - -error[E0423]: expected value, found struct `std::cell::Cell` - --> $DIR/issue-22692.rs:17:9 - | -LL | ::std::cell::Cell - | ^^^^^^^^^^^^^^^^^ -... -LL | let _ = create!(macro method); - | --------------------- in this macro invocation - | - = note: this error originates in the macro `Type` which comes from the expansion of the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) -help: use the path separator to refer to an item - | -LL - Type!().new(0) -LL + ::new(0) - | - -error: aborting due to 8 previous errors - -For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/type/pattern_types/range_patterns.stderr b/tests/ui/type/pattern_types/range_patterns.stderr index 7da8cfd4dbc2..690592ba0b8d 100644 --- a/tests/ui/type/pattern_types/range_patterns.stderr +++ b/tests/ui/type/pattern_types/range_patterns.stderr @@ -31,6 +31,7 @@ error: layout_of(NonZero) = Layout { valid_range: 1..=4294967295, }, ), + uninhabited: false, variants: Single { index: 0, }, @@ -69,6 +70,7 @@ error: layout_of((u32) is 1..=) = Layout { valid_range: 1..=4294967295, }, ), + uninhabited: false, variants: Single { index: 0, }, @@ -105,6 +107,7 @@ error: layout_of(Option<(u32) is 1..=>) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -134,6 +137,7 @@ error: layout_of(Option<(u32) is 1..=>) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -174,6 +178,7 @@ error: layout_of(Option<(u32) is 1..=>) = Layout { valid_range: 1..=4294967295, }, ), + uninhabited: false, variants: Single { index: 1, }, @@ -216,6 +221,7 @@ error: layout_of(Option>) = Layout { ], }, largest_niche: None, + uninhabited: false, variants: Multiple { tag: Initialized { value: Int( @@ -245,6 +251,7 @@ error: layout_of(Option>) = Layout { memory_index: [], }, largest_niche: None, + uninhabited: false, variants: Single { index: 0, }, @@ -285,6 +292,7 @@ error: layout_of(Option>) = Layout { valid_range: 1..=4294967295, }, ), + uninhabited: false, variants: Single { index: 1, }, @@ -336,6 +344,7 @@ error: layout_of(NonZeroU32New) = Layout { valid_range: 1..=4294967295, }, ), + uninhabited: false, variants: Single { index: 0, }, diff --git a/tests/ui/uninhabited/uninhabited-transparent-return-abi.rs b/tests/ui/uninhabited/uninhabited-transparent-return-abi.rs new file mode 100644 index 000000000000..2c2788a3e564 --- /dev/null +++ b/tests/ui/uninhabited/uninhabited-transparent-return-abi.rs @@ -0,0 +1,33 @@ +//@ run-pass +//@ needs-unwind +// See https://github.com/rust-lang/rust/issues/135802 + +enum Void {} + +// Should be ABI-compatible with T, but wasn't prior to the PR adding this test. +#[repr(transparent)] +struct NoReturn(T, Void); + +// Returned by invisible reference (in most ABIs) +#[allow(dead_code)] +struct Large(u64, u64, u64); + +// Prior to the PR adding this test, this function had a different ABI than +// `fn() -> Large` (on `x86_64-unknown-linux-gnu` at least), so calling it as `fn() -> Large` +// would pass the return place pointer in rdi and `correct` in rsi, but the function +// would expect `correct` in rdi. +fn never(correct: &mut bool) -> NoReturn { + *correct = true; + panic!("catch this") +} + +fn main() { + let mut correct = false; + let never: fn(&mut bool) -> NoReturn = never; + // Safety: `NoReturn` is a `repr(transparent)` wrapper around `Large`, + // so they should be ABI-compatible. + let never: fn(&mut bool) -> Large = unsafe { std::mem::transmute(never) }; + let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| never(&mut correct))); + assert!(result.is_err(), "function should have panicked"); + assert!(correct, "function should have stored `true` into `correct`"); +}