diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 7d991e21ff3d2..8dffbd8ff8e88 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3855,14 +3855,26 @@ impl<'hir> Node<'hir> { mod size_asserts { use super::*; use rustc_data_structures::static_assert_size; - // tidy-alphabetical-start static_assert_size!(Block<'_>, 48); static_assert_size!(Body<'_>, 24); + #[cfg(bootstrap)] static_assert_size!(Expr<'_>, 64); + #[cfg(not(bootstrap))] + static_assert_size!(Expr<'_>, 56); + #[cfg(bootstrap)] static_assert_size!(ExprKind<'_>, 48); + #[cfg(not(bootstrap))] + static_assert_size!(ExprKind<'_>, 40); static_assert_size!(FnDecl<'_>, 40); + #[cfg(bootstrap)] static_assert_size!(ForeignItem<'_>, 72); + #[cfg(not(bootstrap))] + static_assert_size!(ForeignItem<'_>, 64); + #[cfg(bootstrap)] static_assert_size!(ForeignItemKind<'_>, 40); + #[cfg(not(bootstrap))] + static_assert_size!(ForeignItemKind<'_>, 32); + // tidy-alphabetical-start static_assert_size!(GenericArg<'_>, 24); static_assert_size!(GenericBound<'_>, 48); static_assert_size!(Generics<'_>, 56); diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs index 62711e40049a4..d76c31f3632d4 100644 --- a/compiler/rustc_hir_typeck/src/intrinsicck.rs +++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs @@ -4,7 +4,7 @@ use rustc_hir as hir; use rustc_index::Idx; use rustc_middle::ty::layout::{LayoutError, SizeSkeleton}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; -use rustc_target::abi::{Pointer, VariantIdx}; +use rustc_target::abi::{Pointer, Size, VariantIdx}; use super::FnCtxt; @@ -84,19 +84,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + fn size_to_bits(size: Size) -> u128 { + let Some(bits) = u128::from(size.bytes()).checked_mul(8) else { + // `u128` should definitely be able to hold the size of different architectures + // larger sizes should be reported as error `are too big for the current architecture` + // otherwise we have a bug somewhere + bug!("{:?} overflow for u128", size) + }; + + bits + } + // Try to display a sensible error with as much information as possible. let skeleton_string = |ty: Ty<'tcx>, sk: Result<_, &_>| match sk { - Ok(SizeSkeleton::Pointer { tail, .. }) => format!("pointer to `{tail}`"), - Ok(SizeSkeleton::Known(size)) => { - if let Some(v) = u128::from(size.bytes()).checked_mul(8) { - format!("{v} bits") - } else { - // `u128` should definitely be able to hold the size of different architectures - // larger sizes should be reported as error `are too big for the current architecture` - // otherwise we have a bug somewhere - bug!("{:?} overflow for u128", size) - } + Ok(SizeSkeleton::Pointer { tail, known_size: Some(size), .. }) => { + format!("{} bits, pointer to `{tail}`", size_to_bits(size)) } + Ok(SizeSkeleton::Pointer { tail, .. }) => format!("pointer to `{tail}`"), + Ok(SizeSkeleton::Known(size)) => format!("{} bits", size_to_bits(size)), Ok(SizeSkeleton::Generic(size)) => { if let Some(size) = size.try_eval_target_usize(tcx, self.param_env) { format!("{size} bytes") diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index cf701f837d895..65b40933d8da0 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -3,6 +3,7 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::query::TyCtxtAt; use crate::ty::normalize_erasing_regions::NormalizationError; use crate::ty::{self, Ty, TyCtxt, TypeVisitableExt}; +use hir::Mutability; use rustc_error_messages::DiagMessage; use rustc_errors::{ Diag, DiagArgValue, DiagCtxt, Diagnostic, EmissionGuarantee, IntoDiagArg, Level, @@ -319,6 +320,8 @@ pub enum SizeSkeleton<'tcx> { Pointer { /// If true, this pointer is never null. non_zero: bool, + /// Available if the width of the pointer is known, i.e. whether it's 1 or 2 usizes + known_size: Option, /// The type which determines the unsized metadata, if any, /// of this pointer. Either a type parameter or a projection /// depending on one, with regions erased. @@ -372,7 +375,23 @@ impl<'tcx> SizeSkeleton<'tcx> { match tail.kind() { ty::Param(_) | ty::Alias(ty::Projection | ty::Inherent, _) => { debug_assert!(tail.has_non_region_param()); - Ok(SizeSkeleton::Pointer { non_zero, tail: tcx.erase_regions(tail) }) + Ok(SizeSkeleton::Pointer { + non_zero, + known_size: None, + tail: tcx.erase_regions(tail), + }) + } + ty::Slice(_) => { + debug_assert!(tail.has_non_region_param()); + // Assumption: all slice pointers have the same size. At most they differ in niches or or ptr/len ordering + let simple_slice = + Ty::new_ptr(tcx, Ty::new_slice(tcx, tcx.types.unit), Mutability::Not); + let size = tcx.layout_of(param_env.and(simple_slice)).unwrap().size; + Ok(SizeSkeleton::Pointer { + non_zero, + known_size: Some(size), + tail: tcx.erase_regions(tail), + }) } ty::Error(guar) => { // Fixes ICE #124031 @@ -449,7 +468,7 @@ impl<'tcx> SizeSkeleton<'tcx> { let v0 = zero_or_ptr_variant(0)?; // Newtype. if def.variants().len() == 1 { - if let Some(SizeSkeleton::Pointer { non_zero, tail }) = v0 { + if let Some(SizeSkeleton::Pointer { non_zero, known_size, tail }) = v0 { return Ok(SizeSkeleton::Pointer { non_zero: non_zero || match tcx.layout_scalar_valid_range(def.did()) { @@ -459,6 +478,7 @@ impl<'tcx> SizeSkeleton<'tcx> { } _ => false, }, + known_size, tail, }); } else { @@ -469,9 +489,9 @@ impl<'tcx> SizeSkeleton<'tcx> { let v1 = zero_or_ptr_variant(1)?; // Nullable pointer enum optimization. match (v0, v1) { - (Some(SizeSkeleton::Pointer { non_zero: true, tail }), None) - | (None, Some(SizeSkeleton::Pointer { non_zero: true, tail })) => { - Ok(SizeSkeleton::Pointer { non_zero: false, tail }) + (Some(SizeSkeleton::Pointer { non_zero: true, known_size, tail }), None) + | (None, Some(SizeSkeleton::Pointer { non_zero: true, known_size, tail })) => { + Ok(SizeSkeleton::Pointer { non_zero: false, known_size, tail }) } _ => Err(err), } @@ -492,7 +512,10 @@ impl<'tcx> SizeSkeleton<'tcx> { pub fn same_size(self, other: SizeSkeleton<'tcx>) -> bool { match (self, other) { - (SizeSkeleton::Known(a), SizeSkeleton::Known(b)) => a == b, + ( + SizeSkeleton::Known(a) | SizeSkeleton::Pointer { known_size: Some(a), .. }, + SizeSkeleton::Known(b) | SizeSkeleton::Pointer { known_size: Some(b), .. }, + ) => a == b, (SizeSkeleton::Pointer { tail: a, .. }, SizeSkeleton::Pointer { tail: b, .. }) => { a == b } diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index f78a28d16fdf5..6f58cd94a1a54 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -1,3 +1,4 @@ +use crate::layout::ty::ParamEnv; use hir::def_id::DefId; use rustc_hir as hir; use rustc_index::bit_set::BitSet; @@ -15,9 +16,12 @@ use rustc_session::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo}; use rustc_span::sym; use rustc_span::symbol::Symbol; use rustc_target::abi::*; +use rustc_type_ir::DynKind; +use std::cmp; use std::fmt::Debug; use std::iter; +use std::ops::ControlFlow; use crate::errors::{ MultipleArrayFieldsSimdType, NonPrimitiveSimdType, OversizedSimdType, ZeroLengthSimdType, @@ -125,7 +129,8 @@ fn layout_of_uncached<'tcx>( }; debug_assert!(!ty.has_non_region_infer()); - Ok(match *ty.kind() { + + let layout = match *ty.kind() { ty::Pat(ty, pat) => { let layout = cx.layout_of(ty)?.layout; let mut layout = LayoutS::clone(&layout.0); @@ -162,7 +167,6 @@ fn layout_of_uncached<'tcx>( } } } - // Basic scalars. ty::Bool => tcx.mk_layout(LayoutS::scalar( cx, @@ -235,10 +239,32 @@ fn layout_of_uncached<'tcx>( return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr))); } - let Abi::Scalar(metadata) = metadata_layout.abi else { + let Abi::Scalar(mut metadata) = metadata_layout.abi else { return Err(error(cx, LayoutError::Unknown(pointee))); }; + if !ty.is_unsafe_ptr() && metadata_ty == tcx.types.usize { + let tail = tcx.struct_tail_erasing_lifetimes(pointee, param_env); + // // eprintln!("usize-meta {:?} {}", pointee, pointee_zst); + match tail.kind() { + ty::Slice(element) => match ty_is_non_zst(*element, param_env, tcx) { + NonZst::True => { + metadata.valid_range_mut().end = + dl.ptr_sized_integer().signed_max() as u128 + } + NonZst::Unknown => return Err(error(cx, LayoutError::Unknown(ty))), + _ => {} + }, + ty::Str => { + metadata.valid_range_mut().end = + dl.ptr_sized_integer().signed_max() as u128; + } + _ => { + eprint!("unexpected tail {:?}", tail); + } + } + } + metadata } else { let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env); @@ -247,7 +273,28 @@ fn layout_of_uncached<'tcx>( ty::Foreign(..) => { return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr))); } - ty::Slice(_) | ty::Str => scalar_unit(Int(dl.ptr_sized_integer(), false)), + ty::Slice(element) => { + let mut metadata = scalar_unit(Int(dl.ptr_sized_integer(), false)); + if !ty.is_unsafe_ptr() { + match ty_is_non_zst(*element, param_env, tcx) { + NonZst::True => { + metadata.valid_range_mut().end = + dl.ptr_sized_integer().signed_max() as u128 + } + NonZst::Unknown => return Err(error(cx, LayoutError::Unknown(ty))), + _ => {} + } + } + metadata + } + ty::Str => { + let mut metadata = scalar_unit(Int(dl.ptr_sized_integer(), false)); + if !ty.is_unsafe_ptr() { + metadata.valid_range_mut().end = + dl.ptr_sized_integer().signed_max() as u128; + } + metadata + } ty::Dynamic(..) => { let mut vtable = scalar_unit(Pointer(AddressSpace::DATA)); vtable.valid_range_mut().start = 1; @@ -674,7 +721,149 @@ fn layout_of_uncached<'tcx>( ty::Placeholder(..) | ty::Param(_) => { return Err(error(cx, LayoutError::Unknown(ty))); } - }) + }; + + #[cfg(debug_assertions)] + if layout.is_sized() && !layout.abi.is_uninhabited() { + match (ty_is_non_zst(ty, param_env, tcx), layout.is_zst()) { + (NonZst::Unknown, _) => { + bug!("ZSTness should not be unknown at this point {:?} {:?}", ty, layout) + } + (NonZst::False | NonZst::Uninhabited, false) => { + bug!("{:?} is not a ZST but ty_is_non_zst() thinks it is", ty) + } + (NonZst::True, true) => bug!("{:?} is a ZST but ty_is_non_zst() thinks it isn't", ty), + _ => {} + } + } + + Ok(layout) +} + +fn ty_is_non_zst<'tcx>(ty: Ty<'tcx>, param_env: ParamEnv<'tcx>, tcx: TyCtxt<'tcx>) -> NonZst { + fn fold_fields<'tcx>( + mut it: impl Iterator>, + param_env: ParamEnv<'tcx>, + tcx: TyCtxt<'tcx>, + ) -> NonZst { + let (ControlFlow::Break(res) | ControlFlow::Continue(res)) = + it.try_fold(NonZst::False, |acc, ty| { + if acc == NonZst::True { + return ControlFlow::Break(acc); + } + + ControlFlow::Continue(cmp::max(acc, ty_is_non_zst(ty, param_env, tcx))) + }); + + res + } + + match ty.kind() { + ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) + | ty::Uint(_) + | ty::Int(_) + | ty::Bool + | ty::Float(_) + | ty::FnPtr(_) + | ty::RawPtr(..) + | ty::Dynamic(_, _, DynKind::DynStar) + | ty::Char + | ty::Ref(..) => NonZst::True, + + ty::Pat(ty, _) => ty_is_non_zst(*ty, param_env, tcx), + ty::Closure(_, args) => fold_fields(args.as_closure().upvar_tys().iter(), param_env, tcx), + ty::Coroutine(_, _) => NonZst::True, + ty::CoroutineClosure(_, args) => { + fold_fields(args.as_coroutine_closure().upvar_tys().iter(), param_env, tcx) + } + ty::Array(ty, len) => { + let len = if len.has_aliases() { + tcx.normalize_erasing_regions(param_env, *len) + } else { + *len + }; + + if let Some(len) = len.try_to_target_usize(tcx) { + if len == 0 { + return NonZst::False; + } + let element_zst = ty_is_non_zst(*ty, param_env, tcx); + if element_zst != NonZst::Unknown { + return element_zst; + } + } + NonZst::Unknown + } + ty::Tuple(tys) => fold_fields(tys.iter(), param_env, tcx), + ty::Adt(def, args) => { + if ty.is_enum() { + if def.variants().len() == 0 { + return NonZst::Uninhabited; + } + // An enum is !ZST if + // * it has a repr and at least one non-uninhabited variant + // * it has at least one variant with a !ZST payload + // * it has multiple variants that are not uninhabited + + let min_empty_variants = if def.repr().inhibit_enum_layout_opt() { 1 } else { 2 }; + + // first check without recursing + let simple_variants = def.variants().iter().filter(|v| v.fields.len() == 0).count(); + if simple_variants >= min_empty_variants { + return NonZst::True; + } + + let mut inhabited_zst_variants = 0; + let mut unknown = false; + + for variant in def.variants().iter().filter(|v| v.fields.len() != 0) { + let variant_sized = + fold_fields(variant.fields.iter().map(|f| f.ty(tcx, args)), param_env, tcx); + + match variant_sized { + // enum E { A(!, u32) } counts as !ZST for our purposes + NonZst::True => return NonZst::True, + NonZst::False => inhabited_zst_variants += 1, + NonZst::Unknown => unknown = true, + NonZst::Uninhabited => {} + } + } + + if simple_variants + inhabited_zst_variants >= min_empty_variants { + return NonZst::True; + } + if unknown { + return NonZst::Unknown; + } + if simple_variants + inhabited_zst_variants == 0 { + return NonZst::Uninhabited; + } + + NonZst::False + } else { + fold_fields(def.all_fields().map(|f| f.ty(tcx, args)), param_env, tcx) + } + } + ty::FnDef(..) => NonZst::False, + ty::Never => NonZst::Uninhabited, + ty::Param(..) => NonZst::Unknown, + ty::Str => NonZst::True, + // treat unsized types as potentially-ZST + ty::Dynamic(..) | ty::Slice(..) => NonZst::False, + ty::Alias(..) => match tcx.try_normalize_erasing_regions(param_env, ty) { + Ok(ty) if !matches!(ty.kind(), ty::Alias(..)) => ty_is_non_zst(ty, param_env, tcx), + _ => NonZst::Unknown, + }, + _ => bug!("is_non_zst not implemented for this kind {:?}", ty), + } +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug, PartialOrd, Ord)] +pub enum NonZst { + False, + Uninhabited, + Unknown, + True, } /// Overlap eligibility and variant assignment for each CoroutineSavedLocal. diff --git a/library/alloc/src/vec/is_zero.rs b/library/alloc/src/vec/is_zero.rs index bcc5bf4d65bb4..1a9f782cb2a73 100644 --- a/library/alloc/src/vec/is_zero.rs +++ b/library/alloc/src/vec/is_zero.rs @@ -94,14 +94,12 @@ macro_rules! impl_is_zero_tuples { impl_is_zero_tuples!(A, B, C, D, E, F, G, H); -// `Option<&T>` and `Option>` are guaranteed to represent `None` as null. -// For fat pointers, the bytes that would be the pointer metadata in the `Some` -// variant are padding in the `None` variant, so ignoring them and -// zero-initializing instead is ok. +// For thin pointers `Option<&T>` and `Option>` are guaranteed to represent +// `None` as null. // `Option<&mut T>` never implements `Clone`, so there's no need for an impl of // `SpecFromElem`. -unsafe impl IsZero for Option<&T> { +unsafe impl IsZero for Option<&T> { #[inline] fn is_zero(&self) -> bool { self.is_none() diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs index e388800f400df..03e42e7e71e9c 100644 --- a/library/core/tests/mem.rs +++ b/library/core/tests/mem.rs @@ -776,7 +776,7 @@ fn const_maybe_uninit_zeroed() { // Sanity check for `MaybeUninit::zeroed` in a realistic const situation (plugin array term) #[repr(C)] struct Foo { - a: Option<&'static str>, + a: Option<&'static [u8; 256]>, b: Bar, c: f32, d: *const u8, diff --git a/tests/codegen/intrinsics/transmute.rs b/tests/codegen/intrinsics/transmute.rs index 04a91bb87f7c6..992eb005e3527 100644 --- a/tests/codegen/intrinsics/transmute.rs +++ b/tests/codegen/intrinsics/transmute.rs @@ -371,9 +371,11 @@ pub unsafe fn check_issue_110005(x: (usize, bool)) -> Option> { #[no_mangle] pub unsafe fn check_pair_to_dst_ref<'a>(x: (usize, usize)) -> &'a [u8] { // CHECK: %_0.0 = getelementptr i8, ptr null, i64 %x.0 - // CHECK: %0 = insertvalue { ptr, i64 } poison, ptr %_0.0, 0 - // CHECK: %1 = insertvalue { ptr, i64 } %0, i64 %x.1, 1 - // CHECK: ret { ptr, i64 } %1 + // CHECK: %0 = icmp ule i64 %x.1, 9223372036854775807 + // CHECK: call void @llvm.assume(i1 %0) + // CHECK: %1 = insertvalue { ptr, i64 } poison, ptr %_0.0, 0 + // CHECK: %2 = insertvalue { ptr, i64 } %1, i64 %x.1, 1 + // CHECK: ret { ptr, i64 } %2 transmute(x) } diff --git a/tests/codegen/overaligned-constant.rs b/tests/codegen/overaligned-constant.rs index 7cd8d19c21135..3feb05d365798 100644 --- a/tests/codegen/overaligned-constant.rs +++ b/tests/codegen/overaligned-constant.rs @@ -7,7 +7,8 @@ struct S(i32); -struct SmallStruct(f32, Option, &'static [f32]); +#[repr(C)] +struct SmallStruct(Option, f32, &'static [f32]); // CHECK: @0 = private unnamed_addr constant // CHECK-SAME: , align 8 @@ -17,14 +18,14 @@ pub fn overaligned_constant() { // CHECK-LABEL: @overaligned_constant // CHECK: [[full:%_.*]] = alloca [32 x i8], align 8 // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[full]], ptr align 8 @0, i64 32, i1 false) - // CHECK: %b.0 = load i32, ptr @0, align 4 - // CHECK: %b.1 = load i32, ptr getelementptr inbounds ({{.*}}), align 4 + // CHECK: %a.0 = load i32, ptr @0, align 4 + // CHECK: %a.1 = load i32, ptr getelementptr inbounds ({{.*}}), align 4 let mut s = S(1); s.0 = 3; // SMALL_VAL corresponds to a MIR allocation with alignment 8. - const SMALL_VAL: SmallStruct = SmallStruct(4., Some(S(1)), &[]); + const SMALL_VAL: SmallStruct = SmallStruct(Some(S(1)), 4., &[]); // In pre-codegen MIR: // `a` is a scalar 4. diff --git a/tests/codegen/slice-indexing.rs b/tests/codegen/slice-indexing.rs index 3d284148db22e..92b411be5221a 100644 --- a/tests/codegen/slice-indexing.rs +++ b/tests/codegen/slice-indexing.rs @@ -36,7 +36,7 @@ pub unsafe fn get_unchecked_mut_by_range(x: &mut [i32], r: Range) -> &mut // CHECK-LABEL: @str_index_by_range( #[no_mangle] pub fn str_index_by_range(x: &str, r: Range) -> &str { - // CHECK: sub nuw i64 + // CHECK: sub nuw nsw i64 &x[r] } @@ -50,7 +50,7 @@ pub unsafe fn str_get_unchecked_by_range(x: &str, r: Range) -> &str { // CHECK-LABEL: @str_index_mut_by_range( #[no_mangle] pub fn str_index_mut_by_range(x: &mut str, r: Range) -> &mut str { - // CHECK: sub nuw i64 + // CHECK: sub nuw nsw i64 &mut x[r] } diff --git a/tests/codegen/slice-len.rs b/tests/codegen/slice-len.rs new file mode 100644 index 0000000000000..3d61aff603ae9 --- /dev/null +++ b/tests/codegen/slice-len.rs @@ -0,0 +1,13 @@ +// @compile-flags: -O +#![crate_type = "lib"] + +// check that slice.len() has range metadata + +// CHECK-LABEL: @slice_len +#[no_mangle] +pub fn slice_len(slice: &&[i32]) -> usize { + // CHECK: load {{i64|i32}} + // CHECK-SAME: !range + slice.len() + // CHECK: ret +} diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff index c2608190a6b97..3faf8ca595063 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff @@ -224,8 +224,8 @@ } ALLOC0 (size: 32, align: 8) { - 0x00 │ 01 00 00 00 23 00 00 00 ╾ALLOC1╼ │ ....#...╾──────╼ - 0x10 │ 02 00 00 00 00 00 00 00 00 00 a4 42 __ __ __ __ │ ...........B░░░░ + 0x00 │ ╾ALLOC1╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x10 │ 01 00 00 00 23 00 00 00 00 00 a4 42 __ __ __ __ │ ....#......B░░░░ } ALLOC1 (size: 8, align: 4) { @@ -237,8 +237,8 @@ } ALLOC2 (size: 32, align: 8) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾ALLOC3╼ │ ....░░░░╾──────╼ - 0x10 │ 01 00 00 00 00 00 00 00 00 00 10 41 __ __ __ __ │ ...........A░░░░ + 0x00 │ ╾ALLOC3╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x10 │ 00 00 00 00 __ __ __ __ 00 00 10 41 __ __ __ __ │ ....░░░░...A░░░░ } ALLOC3 (size: 4, align: 4) { diff --git a/tests/rustdoc/type-layout.rs b/tests/rustdoc/type-layout.rs index b2ff4add63e2b..36d6e2f3d4072 100644 --- a/tests/rustdoc/type-layout.rs +++ b/tests/rustdoc/type-layout.rs @@ -60,7 +60,7 @@ pub type TypeAlias = X; pub type GenericTypeAlias = (Generic<(u32, ())>, Generic); // Regression test for the rustdoc equivalent of #85103. -// @hasraw type_layout/type.Edges.html 'Encountered an error during type layout; the type failed to be normalized.' +// @hasraw type_layout/type.Edges.html 'Unable to compute type layout, possibly due to this type having generic parameters' pub type Edges<'a, E> = std::borrow::Cow<'a, [E]>; // @!hasraw type_layout/trait.MyTrait.html 'Size: ' diff --git a/tests/ui/issues/issue-28625.stderr b/tests/ui/issues/issue-28625.stderr index 3600622a45424..dc7e87c6c2968 100644 --- a/tests/ui/issues/issue-28625.stderr +++ b/tests/ui/issues/issue-28625.stderr @@ -5,7 +5,7 @@ LL | unsafe { std::mem::transmute(a) } | ^^^^^^^^^^^^^^^^^^^ | = note: source type: `&ArrayPeano` (N bits) - = note: target type: `&[T]` (N bits) + = note: target type: `&[T]` (N bits, pointer to `[T]`) error: aborting due to 1 previous error diff --git a/tests/ui/stats/hir-stats.rs b/tests/ui/stats/hir-stats.rs index 249413d80e82a..eeb7bc39dec00 100644 --- a/tests/ui/stats/hir-stats.rs +++ b/tests/ui/stats/hir-stats.rs @@ -1,7 +1,7 @@ //@ check-pass //@ compile-flags: -Zhir-stats //@ only-x86_64 - +//@ ignore-stage1 // Type layouts sometimes change. When that happens, until the next bootstrap // bump occurs, stage1 and stage2 will give different outputs for this test. // Add an `ignore-stage1` comment marker to work around that problem during diff --git a/tests/ui/stats/hir-stats.stderr b/tests/ui/stats/hir-stats.stderr index a3d0d47d40756..a5321fb457c0c 100644 --- a/tests/ui/stats/hir-stats.stderr +++ b/tests/ui/stats/hir-stats.stderr @@ -141,38 +141,38 @@ hir-stats FnDecl 120 ( 1.3%) 3 40 hir-stats Attribute 128 ( 1.4%) 4 32 hir-stats Variant 144 ( 1.6%) 2 72 hir-stats GenericArgs 144 ( 1.6%) 3 48 -hir-stats GenericBound 192 ( 2.1%) 4 48 -hir-stats - Trait 192 ( 2.1%) 4 -hir-stats WherePredicate 192 ( 2.1%) 3 64 -hir-stats - BoundPredicate 192 ( 2.1%) 3 +hir-stats GenericBound 192 ( 2.2%) 4 48 +hir-stats - Trait 192 ( 2.2%) 4 +hir-stats WherePredicate 192 ( 2.2%) 3 64 +hir-stats - BoundPredicate 192 ( 2.2%) 3 hir-stats Block 288 ( 3.2%) 6 48 hir-stats GenericParam 360 ( 4.0%) 5 72 hir-stats Pat 360 ( 4.0%) 5 72 hir-stats - Wild 72 ( 0.8%) 1 hir-stats - Struct 72 ( 0.8%) 1 hir-stats - Binding 216 ( 2.4%) 3 -hir-stats Generics 560 ( 6.2%) 10 56 -hir-stats Ty 720 ( 8.0%) 15 48 +hir-stats Generics 560 ( 6.3%) 10 56 +hir-stats Expr 672 ( 7.6%) 12 56 +hir-stats - Path 56 ( 0.6%) 1 +hir-stats - Struct 56 ( 0.6%) 1 +hir-stats - Match 56 ( 0.6%) 1 +hir-stats - InlineAsm 56 ( 0.6%) 1 +hir-stats - Lit 112 ( 1.3%) 2 +hir-stats - Block 336 ( 3.8%) 6 +hir-stats Ty 720 ( 8.1%) 15 48 hir-stats - Ptr 48 ( 0.5%) 1 hir-stats - Ref 48 ( 0.5%) 1 -hir-stats - Path 624 ( 6.9%) 13 -hir-stats Expr 768 ( 8.5%) 12 64 -hir-stats - Path 64 ( 0.7%) 1 -hir-stats - Struct 64 ( 0.7%) 1 -hir-stats - Match 64 ( 0.7%) 1 -hir-stats - InlineAsm 64 ( 0.7%) 1 -hir-stats - Lit 128 ( 1.4%) 2 -hir-stats - Block 384 ( 4.3%) 6 -hir-stats Item 968 (10.8%) 11 88 +hir-stats - Path 624 ( 7.0%) 13 +hir-stats Item 968 (10.9%) 11 88 hir-stats - Trait 88 ( 1.0%) 1 hir-stats - Enum 88 ( 1.0%) 1 hir-stats - ExternCrate 88 ( 1.0%) 1 hir-stats - ForeignMod 88 ( 1.0%) 1 hir-stats - Impl 88 ( 1.0%) 1 hir-stats - Fn 176 ( 2.0%) 2 -hir-stats - Use 352 ( 3.9%) 4 -hir-stats Path 1_240 (13.8%) 31 40 -hir-stats PathSegment 1_920 (21.4%) 40 48 +hir-stats - Use 352 ( 4.0%) 4 +hir-stats Path 1_240 (13.9%) 31 40 +hir-stats PathSegment 1_920 (21.6%) 40 48 hir-stats ---------------------------------------------------------------- -hir-stats Total 8_992 +hir-stats Total 8_896 hir-stats diff --git a/tests/ui/transmute/transmute-fat-pointers.stderr b/tests/ui/transmute/transmute-fat-pointers.stderr index e8335fcbed9d0..c89e8e24727a0 100644 --- a/tests/ui/transmute/transmute-fat-pointers.stderr +++ b/tests/ui/transmute/transmute-fat-pointers.stderr @@ -4,7 +4,7 @@ error[E0512]: cannot transmute between types of different sizes, or dependently- LL | unsafe { transmute(x) } | ^^^^^^^^^ | - = note: source type: `&[T]` (N bits) + = note: source type: `&[T]` (N bits, pointer to `[T]`) = note: target type: `&U` (pointer to `U`) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types