From d0a5bbbb8e394095848e078a3fff72beaad14209 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Sun, 16 Feb 2025 00:03:10 +0100 Subject: [PATCH 1/6] document and test all `LayoutError` variants --- compiler/rustc_middle/src/ty/layout.rs | 21 ++++++++ tests/ui/layout/debug.rs | 5 ++ tests/ui/layout/debug.stderr | 8 ++- tests/ui/layout/normalization-failure.rs | 57 ++++++++++++++++++++ tests/ui/layout/normalization-failure.stderr | 12 +++++ 5 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 tests/ui/layout/normalization-failure.rs create mode 100644 tests/ui/layout/normalization-failure.stderr diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index bbb8a9fa67149..2a058addf1597 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -229,11 +229,32 @@ impl fmt::Display for ValidityRequirement { #[derive(Copy, Clone, Debug, HashStable, TyEncodable, TyDecodable)] pub enum LayoutError<'tcx> { + /// A type doesn't have a sensible layout. + /// + /// This variant is used for layout errors that don't necessarily cause + /// compile errors. + /// + /// For example, this can happen if a struct contains an unsized type in a + /// non-tail field, but has an unsatisfiable bound like `str: Sized`. Unknown(Ty<'tcx>), + /// The size of a type exceeds [`TargetDataLayout::obj_size_bound`]. SizeOverflow(Ty<'tcx>), + /// The layout can vary due to a generic parameter. + /// + /// Unlike `Unknown`, this variant is a "soft" error and indicates that the layout + /// may become computable after further instantiating the generic parameter(s). TooGeneric(Ty<'tcx>), + /// An alias failed to normalize. + /// + /// This variant is necessary, because, due to trait solver incompleteness, it is + /// possible than an alias that was rigid during analysis fails to normalize after + /// revealing opaque types. + /// + /// See `tests/ui/layout/normalization-failure.rs` for an example. NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>), + /// A non-layout error is reported elsewhere. ReferencesError(ErrorGuaranteed), + /// A type has cyclic layout, i.e. the type contains itself without indirection. Cycle(ErrorGuaranteed), } diff --git a/tests/ui/layout/debug.rs b/tests/ui/layout/debug.rs index 81dc72852543d..c0adf9ec67763 100644 --- a/tests/ui/layout/debug.rs +++ b/tests/ui/layout/debug.rs @@ -82,3 +82,8 @@ type Impossible = (str, str); //~ ERROR: cannot be known at compilation time #[rustc_layout(debug)] union EmptyUnion {} //~ ERROR: has an unknown layout //~^ ERROR: unions cannot have zero fields + +// Test the error message of `LayoutError::TooGeneric` +// (this error is never emitted to users). +#[rustc_layout(debug)] +type TooGeneric = T; //~ ERROR: does not have a fixed size diff --git a/tests/ui/layout/debug.stderr b/tests/ui/layout/debug.stderr index 319c0de26a90e..d64dee4e27fc3 100644 --- a/tests/ui/layout/debug.stderr +++ b/tests/ui/layout/debug.stderr @@ -596,12 +596,18 @@ error: the type has an unknown layout LL | union EmptyUnion {} | ^^^^^^^^^^^^^^^^ +error: `T` does not have a fixed size + --> $DIR/debug.rs:89:1 + | +LL | type TooGeneric = T; + | ^^^^^^^^^^^^^^^^^^ + error: `#[rustc_layout]` can only be applied to `struct`/`enum`/`union` declarations and type aliases --> $DIR/debug.rs:75:5 | LL | const C: () = (); | ^^^^^^^^^^^ -error: aborting due to 19 previous errors +error: aborting due to 20 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/layout/normalization-failure.rs b/tests/ui/layout/normalization-failure.rs new file mode 100644 index 0000000000000..c0f8710c03cb3 --- /dev/null +++ b/tests/ui/layout/normalization-failure.rs @@ -0,0 +1,57 @@ +//! This test demonstrates how `LayoutError::NormalizationFailure` can happen and why +//! it is necessary. +//! +//! This code does not cause an immediate normalization error in typeck, because we +//! don't reveal the hidden type returned by `opaque` in the analysis typing mode. +//! Instead, `<{opaque} as Project2>::Assoc2` is a *rigid projection*, because we know +//! that `{opaque}: Project2` holds, due to the opaque type's `impl Project2` bound, +//! but cannot normalize `<{opaque} as Project2>::Assoc2` any further. +//! +//! However, in the post-analysis typing mode, which is used for the layout computation, +//! the opaque's hidden type is revealed to be `PhantomData`, and now we fail to +//! normalize ` as Project2>::Assoc2` if there is a `T: Project1` bound +//! in the param env! This happens, because `PhantomData: Project2` only holds if +//! `::Assoc1 == ()` holds. This would usually be satisfied by the +//! blanket `impl Project1 for T`, but due to the `T: Project1` bound we do not +//! normalize `::Assoc1` via the impl and treat it as rigid instead. +//! Therefore, `PhantomData: Project2` does NOT hold and normalizing +//! ` as Project2>::Assoc2` fails. +//! +//! Note that this layout error can only happen when computing the layout in a generic +//! context, which is not required for codegen, but may happen for lints, MIR optimizations, +//! and the transmute check. + +use std::marker::PhantomData; + +trait Project1 { + type Assoc1; +} + +impl Project1 for T { + type Assoc1 = (); +} + +trait Project2 { + type Assoc2; + fn get(self) -> Self::Assoc2; +} + +impl> Project2 for PhantomData { + type Assoc2 = (); + fn get(self) -> Self::Assoc2 {} +} + +fn opaque() -> impl Project2 { + PhantomData:: +} + +fn check() { + unsafe { + std::mem::transmute::<_, ()>(opaque::().get()); + //~^ ERROR: cannot transmute + //~| NOTE: (unable to determine layout for `::Assoc2` because `::Assoc2` cannot be normalized) + //~| NOTE: (0 bits) + } +} + +fn main() {} diff --git a/tests/ui/layout/normalization-failure.stderr b/tests/ui/layout/normalization-failure.stderr new file mode 100644 index 0000000000000..5fe38d4403a20 --- /dev/null +++ b/tests/ui/layout/normalization-failure.stderr @@ -0,0 +1,12 @@ +error[E0512]: cannot transmute between types of different sizes, or dependently-sized types + --> $DIR/normalization-failure.rs:50:9 + | +LL | std::mem::transmute::<_, ()>(opaque::().get()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: source type: `::Assoc2` (unable to determine layout for `::Assoc2` because `::Assoc2` cannot be normalized) + = note: target type: `()` (0 bits) + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0512`. From 802b7abab736166fcb12c2567c743e1da6d6806c Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Sun, 16 Feb 2025 20:26:07 +0100 Subject: [PATCH 2/6] clean up layout error diagnostics - group the fluent slugs together - reword (internal-only) "too generic" error to be more in line with the other errors --- compiler/rustc_middle/messages.ftl | 28 +++++++++++++------------- compiler/rustc_middle/src/error.rs | 10 ++++----- compiler/rustc_middle/src/ty/layout.rs | 12 +++++------ tests/ui/layout/debug.rs | 2 +- tests/ui/layout/debug.stderr | 2 +- 5 files changed, 27 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl index dcfa81dab2526..0b3c0be1a4e1a 100644 --- a/compiler/rustc_middle/messages.ftl +++ b/compiler/rustc_middle/messages.ftl @@ -37,9 +37,6 @@ middle_autodiff_unsafe_inner_const_ref = reading from a `Duplicated` const {$ty} middle_bounds_check = index out of bounds: the length is {$len} but the index is {$index} -middle_cannot_be_normalized = - unable to determine layout for `{$ty}` because `{$failure_ty}` cannot be normalized - middle_conflict_types = this expression supplies two conflicting concrete types for the same opaque type @@ -52,9 +49,6 @@ middle_const_eval_non_int = middle_const_not_used_in_type_alias = const parameter `{$ct}` is part of concrete type but not used in parameter list for the `impl Trait` type alias -middle_cycle = - a cycle occurred during layout computation - middle_deprecated = use of deprecated {$kind} `{$path}`{$has_note -> [true] : {$note} *[other] {""} @@ -78,9 +72,23 @@ middle_erroneous_constant = erroneous constant encountered middle_failed_writing_file = failed to write file {$path}: {$error}" +middle_layout_cycle = + a cycle occurred during layout computation + +middle_layout_normalization_failure = + unable to determine layout for `{$ty}` because `{$failure_ty}` cannot be normalized + middle_layout_references_error = the type has an unknown layout +middle_layout_size_overflow = + values of the type `{$ty}` are too big for the target architecture + +middle_layout_too_generic = the type `{$ty}` does not have a fixed layout + +middle_layout_unknown = + the type `{$ty}` has an unknown layout + middle_opaque_hidden_type_mismatch = concrete type differs from previous defining opaque type use .label = expected `{$self_ty}`, got `{$other_ty}` @@ -98,16 +106,8 @@ middle_strict_coherence_needs_negative_coherence = to use `strict_coherence` on this trait, the `with_negative_coherence` feature must be enabled .label = due to this attribute -middle_too_generic = `{$ty}` does not have a fixed size - middle_type_length_limit = reached the type-length limit while instantiating `{$shrunk}` -middle_unknown_layout = - the type `{$ty}` has an unknown layout - middle_unsupported_union = we don't support unions yet: '{$ty_name}' -middle_values_too_big = - values of the type `{$ty}` are too big for the target architecture - middle_written_to_path = the full type name has been written to '{$path}' diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs index c53e3d54cc491..be8a3403ba956 100644 --- a/compiler/rustc_middle/src/error.rs +++ b/compiler/rustc_middle/src/error.rs @@ -132,19 +132,19 @@ impl fmt::Debug for CustomSubdiagnostic<'_> { #[derive(Diagnostic)] pub enum LayoutError<'tcx> { - #[diag(middle_unknown_layout)] + #[diag(middle_layout_unknown)] Unknown { ty: Ty<'tcx> }, - #[diag(middle_too_generic)] + #[diag(middle_layout_too_generic)] TooGeneric { ty: Ty<'tcx> }, - #[diag(middle_values_too_big)] + #[diag(middle_layout_size_overflow)] Overflow { ty: Ty<'tcx> }, - #[diag(middle_cannot_be_normalized)] + #[diag(middle_layout_normalization_failure)] NormalizationFailure { ty: Ty<'tcx>, failure_ty: String }, - #[diag(middle_cycle)] + #[diag(middle_layout_cycle)] Cycle, #[diag(middle_layout_references_error)] diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 2a058addf1597..19fa832357499 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -264,11 +264,11 @@ impl<'tcx> LayoutError<'tcx> { use crate::fluent_generated::*; match self { - Unknown(_) => middle_unknown_layout, - SizeOverflow(_) => middle_values_too_big, - TooGeneric(_) => middle_too_generic, - NormalizationFailure(_, _) => middle_cannot_be_normalized, - Cycle(_) => middle_cycle, + Unknown(_) => middle_layout_unknown, + SizeOverflow(_) => middle_layout_size_overflow, + TooGeneric(_) => middle_layout_too_generic, + NormalizationFailure(_, _) => middle_layout_normalization_failure, + Cycle(_) => middle_layout_cycle, ReferencesError(_) => middle_layout_references_error, } } @@ -297,7 +297,7 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> { match *self { LayoutError::Unknown(ty) => write!(f, "the type `{ty}` has an unknown layout"), LayoutError::TooGeneric(ty) => { - write!(f, "`{ty}` does not have a fixed size") + write!(f, "the type `{ty}` does not have a fixed layout") } LayoutError::SizeOverflow(ty) => { write!(f, "values of the type `{ty}` are too big for the target architecture") diff --git a/tests/ui/layout/debug.rs b/tests/ui/layout/debug.rs index c0adf9ec67763..b87a1d2031df4 100644 --- a/tests/ui/layout/debug.rs +++ b/tests/ui/layout/debug.rs @@ -86,4 +86,4 @@ union EmptyUnion {} //~ ERROR: has an unknown layout // Test the error message of `LayoutError::TooGeneric` // (this error is never emitted to users). #[rustc_layout(debug)] -type TooGeneric = T; //~ ERROR: does not have a fixed size +type TooGeneric = T; //~ ERROR: does not have a fixed layout diff --git a/tests/ui/layout/debug.stderr b/tests/ui/layout/debug.stderr index d64dee4e27fc3..0daf2d3b9e7f2 100644 --- a/tests/ui/layout/debug.stderr +++ b/tests/ui/layout/debug.stderr @@ -596,7 +596,7 @@ error: the type has an unknown layout LL | union EmptyUnion {} | ^^^^^^^^^^^^^^^^ -error: `T` does not have a fixed size +error: the type `T` does not have a fixed layout --> $DIR/debug.rs:89:1 | LL | type TooGeneric = T; From 7a667d206c45b96676c260030a4e3d9be1cc8495 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Sun, 16 Feb 2025 00:19:56 +0100 Subject: [PATCH 3/6] remove unreachable cases `ty::Placeholder` is used by the trait solver and computing its layout was necessary, because the `PointerLike` trait used to be automatically implemented for all types with pointer-like layout. Nowadays, `PointerLike` requires user-written impls and the trait solver no longer computes any layouts, so this can be removed. Unevaluated constants that aren't generic should have caused a const eval error earlier during normalization. --- compiler/rustc_ty_utils/src/layout.rs | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 8429e68b600da..f9ce709d07cb6 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -155,19 +155,12 @@ fn extract_const_value<'tcx>( ty::ConstKind::Error(guar) => { return Err(error(cx, LayoutError::ReferencesError(guar))); } - ty::ConstKind::Param(_) | ty::ConstKind::Expr(_) => { + ty::ConstKind::Param(_) | ty::ConstKind::Expr(_) | ty::ConstKind::Unevaluated(_) => { if !const_.has_param() { - bug!("no generic type found in the type: {ty:?}"); + bug!("failed to normalize const, but it is not generic: {const_:?}"); } return Err(error(cx, LayoutError::TooGeneric(ty))); } - ty::ConstKind::Unevaluated(_) => { - if !const_.has_param() { - return Err(error(cx, LayoutError::Unknown(ty))); - } else { - return Err(error(cx, LayoutError::TooGeneric(ty))); - } - } ty::ConstKind::Infer(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => { bug!("unexpected type: {ty:?}"); } @@ -728,17 +721,17 @@ fn layout_of_uncached<'tcx>( return Err(error(cx, LayoutError::Unknown(ty))); } - ty::Bound(..) | ty::CoroutineWitness(..) | ty::Infer(_) | ty::Error(_) => { - bug!("Layout::compute: unexpected type `{}`", ty) + ty::Placeholder(..) + | ty::Bound(..) + | ty::CoroutineWitness(..) + | ty::Infer(_) + | ty::Error(_) => { + bug!("layout_of: unexpected type `{ty}`") } ty::Param(_) => { return Err(error(cx, LayoutError::TooGeneric(ty))); } - - ty::Placeholder(..) => { - return Err(error(cx, LayoutError::Unknown(ty))); - } }) } From 1d1ac3d310dfe90e1ec91c731f2cc306ddbd1eb4 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Sun, 16 Feb 2025 01:02:18 +0100 Subject: [PATCH 4/6] remove redundant code - we normalize before calling `layout_of_uncached`, so we don't need to normalize again later - we check for type/const errors at the top of `layout_of_uncached`, so we don't need to check again later --- compiler/rustc_ty_utils/src/layout.rs | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index f9ce709d07cb6..5c5558053cc40 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -152,17 +152,19 @@ fn extract_const_value<'tcx>( ) -> Result, &'tcx LayoutError<'tcx>> { match const_.kind() { ty::ConstKind::Value(cv) => Ok(cv), - ty::ConstKind::Error(guar) => { - return Err(error(cx, LayoutError::ReferencesError(guar))); - } ty::ConstKind::Param(_) | ty::ConstKind::Expr(_) | ty::ConstKind::Unevaluated(_) => { if !const_.has_param() { bug!("failed to normalize const, but it is not generic: {const_:?}"); } return Err(error(cx, LayoutError::TooGeneric(ty))); } - ty::ConstKind::Infer(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => { - bug!("unexpected type: {ty:?}"); + ty::ConstKind::Infer(_) + | ty::ConstKind::Bound(..) + | ty::ConstKind::Placeholder(_) + | ty::ConstKind::Error(_) => { + // `ty::ConstKind::Error` is handled at the top of `layout_of_uncached` + // (via `ty.error_reported()`). + bug!("layout_of: unexpected const: {const_:?}"); } } } @@ -267,16 +269,11 @@ fn layout_of_uncached<'tcx>( data_ptr.valid_range_mut().start = 1; } - let pointee = tcx.normalize_erasing_regions(cx.typing_env, pointee); if pointee.is_sized(tcx, cx.typing_env) { return Ok(tcx.mk_layout(LayoutData::scalar(cx, data_ptr))); } - let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type() - // Projection eagerly bails out when the pointee references errors, - // fall back to structurally deducing metadata. - && !pointee.references_error() - { + let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type() { let pointee_metadata = Ty::new_projection(tcx, metadata_def_id, [pointee]); let metadata_ty = match tcx.try_normalize_erasing_regions(cx.typing_env, pointee_metadata) { @@ -726,6 +723,7 @@ fn layout_of_uncached<'tcx>( | ty::CoroutineWitness(..) | ty::Infer(_) | ty::Error(_) => { + // `ty::Error` is handled at the top of this function. bug!("layout_of: unexpected type `{ty}`") } From 67345f9203b451f21aa603329ab657f6e782267c Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Sun, 16 Feb 2025 01:17:08 +0100 Subject: [PATCH 5/6] remove useless parameter Remove the `repr` parameter from the wrappers around `calc.univariant`, because it's always defaulted. Only ADTs can have a repr and those call `calc.layout_of_struct_or_enum` and not `calc.univariant`. --- compiler/rustc_ty_utils/src/layout.rs | 46 ++++++--------------------- 1 file changed, 10 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 5c5558053cc40..36dbddbb9d78a 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -134,15 +134,10 @@ fn univariant_uninterned<'tcx>( cx: &LayoutCx<'tcx>, ty: Ty<'tcx>, fields: &IndexSlice>, - repr: &ReprOptions, kind: StructKind, ) -> Result, &'tcx LayoutError<'tcx>> { - let pack = repr.pack; - if pack.is_some() && repr.align.is_some() { - cx.tcx().dcx().bug("struct cannot be packed and aligned"); - } - - cx.calc.univariant(fields, repr, kind).map_err(|err| map_error(cx, ty, err)) + let repr = ReprOptions::default(); + cx.calc.univariant(fields, &repr, kind).map_err(|err| map_error(cx, ty, err)) } fn extract_const_value<'tcx>( @@ -189,10 +184,9 @@ fn layout_of_uncached<'tcx>( }; let scalar = |value: Primitive| tcx.mk_layout(LayoutData::scalar(cx, scalar_unit(value))); - let univariant = - |fields: &IndexSlice>, repr: &ReprOptions, kind| { - Ok(tcx.mk_layout(univariant_uninterned(cx, ty, fields, repr, kind)?)) - }; + let univariant = |fields: &IndexSlice>, kind| { + Ok(tcx.mk_layout(univariant_uninterned(cx, ty, fields, kind)?)) + }; debug_assert!(!ty.has_non_region_infer()); Ok(match *ty.kind() { @@ -405,17 +399,10 @@ fn layout_of_uncached<'tcx>( }), // Odd unit types. - ty::FnDef(..) => { - univariant(IndexSlice::empty(), &ReprOptions::default(), StructKind::AlwaysSized)? - } + ty::FnDef(..) => univariant(IndexSlice::empty(), StructKind::AlwaysSized)?, ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => { - let mut unit = univariant_uninterned( - cx, - ty, - IndexSlice::empty(), - &ReprOptions::default(), - StructKind::AlwaysSized, - )?; + let mut unit = + univariant_uninterned(cx, ty, IndexSlice::empty(), StructKind::AlwaysSized)?; match unit.backend_repr { BackendRepr::Memory { ref mut sized } => *sized = false, _ => bug!(), @@ -429,7 +416,6 @@ fn layout_of_uncached<'tcx>( let tys = args.as_closure().upvar_tys(); univariant( &tys.iter().map(|ty| cx.layout_of(ty)).try_collect::>()?, - &ReprOptions::default(), StructKind::AlwaysSized, )? } @@ -438,7 +424,6 @@ fn layout_of_uncached<'tcx>( let tys = args.as_coroutine_closure().upvar_tys(); univariant( &tys.iter().map(|ty| cx.layout_of(ty)).try_collect::>()?, - &ReprOptions::default(), StructKind::AlwaysSized, )? } @@ -447,11 +432,7 @@ fn layout_of_uncached<'tcx>( let kind = if tys.len() == 0 { StructKind::AlwaysSized } else { StructKind::MaybeUnsized }; - univariant( - &tys.iter().map(|k| cx.layout_of(k)).try_collect::>()?, - &ReprOptions::default(), - kind, - )? + univariant(&tys.iter().map(|k| cx.layout_of(k)).try_collect::>()?, kind)? } // SIMD vector types. @@ -902,13 +883,7 @@ fn coroutine_layout<'tcx>( .chain(iter::once(Ok(tag_layout))) .chain(promoted_layouts) .try_collect::>()?; - let prefix = univariant_uninterned( - cx, - ty, - &prefix_layouts, - &ReprOptions::default(), - StructKind::AlwaysSized, - )?; + let prefix = univariant_uninterned(cx, ty, &prefix_layouts, StructKind::AlwaysSized)?; let (prefix_size, prefix_align) = (prefix.size, prefix.align); @@ -973,7 +948,6 @@ fn coroutine_layout<'tcx>( cx, ty, &variant_only_tys.map(|ty| cx.layout_of(ty)).try_collect::>()?, - &ReprOptions::default(), StructKind::Prefixed(prefix_size, prefix_align.abi), )?; variant.variants = Variants::Single { index }; From 2fbc413d832486106221253a2db7f4670473ee67 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Sun, 16 Feb 2025 01:32:38 +0100 Subject: [PATCH 6/6] cosmetic changes - change function parameter order to `cx, ty, ...` to match the other functions in this file - use `ct` identifier for `ty::Const` to match the majority of the compiler codebase - remove useless return - bring match arms in a more natural order --- compiler/rustc_ty_utils/src/layout.rs | 40 +++++++++++++++------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 36dbddbb9d78a..556512e0236e5 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -141,17 +141,17 @@ fn univariant_uninterned<'tcx>( } fn extract_const_value<'tcx>( - const_: ty::Const<'tcx>, - ty: Ty<'tcx>, cx: &LayoutCx<'tcx>, + ty: Ty<'tcx>, + ct: ty::Const<'tcx>, ) -> Result, &'tcx LayoutError<'tcx>> { - match const_.kind() { + match ct.kind() { ty::ConstKind::Value(cv) => Ok(cv), ty::ConstKind::Param(_) | ty::ConstKind::Expr(_) | ty::ConstKind::Unevaluated(_) => { - if !const_.has_param() { - bug!("failed to normalize const, but it is not generic: {const_:?}"); + if !ct.has_param() { + bug!("failed to normalize const, but it is not generic: {ct:?}"); } - return Err(error(cx, LayoutError::TooGeneric(ty))); + Err(error(cx, LayoutError::TooGeneric(ty))) } ty::ConstKind::Infer(_) | ty::ConstKind::Bound(..) @@ -159,7 +159,7 @@ fn extract_const_value<'tcx>( | ty::ConstKind::Error(_) => { // `ty::ConstKind::Error` is handled at the top of `layout_of_uncached` // (via `ty.error_reported()`). - bug!("layout_of: unexpected const: {const_:?}"); + bug!("layout_of: unexpected const: {ct:?}"); } } } @@ -199,12 +199,12 @@ fn layout_of_uncached<'tcx>( &mut layout.backend_repr { if let Some(start) = start { - scalar.valid_range_mut().start = extract_const_value(start, ty, cx)? + scalar.valid_range_mut().start = extract_const_value(cx, ty, start)? .try_to_bits(tcx, cx.typing_env) .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?; } if let Some(end) = end { - let mut end = extract_const_value(end, ty, cx)? + let mut end = extract_const_value(cx, ty, end)? .try_to_bits(tcx, cx.typing_env) .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?; if !include_end { @@ -338,7 +338,7 @@ fn layout_of_uncached<'tcx>( // Arrays and slices. ty::Array(element, count) => { - let count = extract_const_value(count, ty, cx)? + let count = extract_const_value(cx, ty, count)? .try_to_target_usize(tcx) .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?; @@ -690,13 +690,21 @@ fn layout_of_uncached<'tcx>( } // Types with no meaningful known layout. + ty::Param(_) => { + return Err(error(cx, LayoutError::TooGeneric(ty))); + } + ty::Alias(..) => { - if ty.has_param() { - return Err(error(cx, LayoutError::TooGeneric(ty))); - } // NOTE(eddyb) `layout_of` query should've normalized these away, // if that was possible, so there's no reason to try again here. - return Err(error(cx, LayoutError::Unknown(ty))); + let err = if ty.has_param() { + LayoutError::TooGeneric(ty) + } else { + // This is only reachable with unsatisfiable predicates. For example, if we have + // `u8: Iterator`, then we can't compute the layout of `::Item`. + LayoutError::Unknown(ty) + }; + return Err(error(cx, err)); } ty::Placeholder(..) @@ -707,10 +715,6 @@ fn layout_of_uncached<'tcx>( // `ty::Error` is handled at the top of this function. bug!("layout_of: unexpected type `{ty}`") } - - ty::Param(_) => { - return Err(error(cx, LayoutError::TooGeneric(ty))); - } }) }