From 52b4de34ec837c09e0ec4c1ce9f00ce8e8b032f8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 27 Feb 2026 17:03:27 +1100 Subject: [PATCH 1/2] Abort after printing infinite type errors. Currently, `Representability::from_cycle_error` prints an "infinite size" error and then returns `Representability::Infinite`, which lets analysis continue. This commit changes it so it just aborts after printing the error. This has two benefits. First, the error messages are better. The error messages we get after continuing are mostly bad -- we usually get another cycle error, e.g. about drop checking or layout, which is not much use to the user, and then abort after that. The only exception is `issue-105231.rs` where a "conflicting implementations" error is now omitted, but there are three other errors before that one so it's no great loss. Second, it allows some simplifications: see the next commit. --- .../rustc_query_impl/src/from_cycle_error.rs | 4 ++- tests/ui/enum-discriminant/issue-72554.rs | 1 - tests/ui/enum-discriminant/issue-72554.stderr | 21 +++------------ tests/ui/infinite/infinite-struct.rs | 2 -- tests/ui/infinite/infinite-struct.stderr | 25 +++--------------- .../infinite/infinite-tag-type-recursion.rs | 1 - .../infinite-tag-type-recursion.stderr | 15 ++--------- .../query-cycle-printing-issue-151226.rs | 2 -- .../query-cycle-printing-issue-151226.stderr | 26 ++----------------- .../structs-enums/enum-rec/issue-17431-6.rs | 1 - .../enum-rec/issue-17431-6.stderr | 15 ++--------- tests/ui/traits/issue-105231.rs | 1 - tests/ui/traits/issue-105231.stderr | 16 ++---------- .../transmute_infinitely_recursive_type.rs | 1 - ...transmute_infinitely_recursive_type.stderr | 13 +++------- 15 files changed, 20 insertions(+), 124 deletions(-) diff --git a/compiler/rustc_query_impl/src/from_cycle_error.rs b/compiler/rustc_query_impl/src/from_cycle_error.rs index a13db9004d678..328bd4a02c8fd 100644 --- a/compiler/rustc_query_impl/src/from_cycle_error.rs +++ b/compiler/rustc_query_impl/src/from_cycle_error.rs @@ -117,8 +117,10 @@ impl<'tcx> FromCycleError<'tcx> for Representability { representable_ids.insert(def_id); } } + // We used to continue here, but the cycle error printed next is actually less useful than + // the error produced by `recursive_type_error`. let guar = recursive_type_error(tcx, item_and_field_ids, &representable_ids); - Representability::Infinite(guar) + guar.raise_fatal(); } } diff --git a/tests/ui/enum-discriminant/issue-72554.rs b/tests/ui/enum-discriminant/issue-72554.rs index 1fe9a5f4faa7d..54f7e9ac592eb 100644 --- a/tests/ui/enum-discriminant/issue-72554.rs +++ b/tests/ui/enum-discriminant/issue-72554.rs @@ -3,7 +3,6 @@ use std::collections::BTreeSet; #[derive(Hash)] pub enum ElemDerived { //~^ ERROR recursive type `ElemDerived` has infinite size - //~| ERROR cycle detected A(ElemDerived) } diff --git a/tests/ui/enum-discriminant/issue-72554.stderr b/tests/ui/enum-discriminant/issue-72554.stderr index 648680c6031da..381f24d351e9c 100644 --- a/tests/ui/enum-discriminant/issue-72554.stderr +++ b/tests/ui/enum-discriminant/issue-72554.stderr @@ -3,7 +3,7 @@ error[E0072]: recursive type `ElemDerived` has infinite size | LL | pub enum ElemDerived { | ^^^^^^^^^^^^^^^^^^^^ -... +LL | LL | A(ElemDerived) | ----------- recursive without indirection | @@ -12,21 +12,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | A(Box) | ++++ + -error[E0391]: cycle detected when computing drop-check constraints for `ElemDerived` - --> $DIR/issue-72554.rs:4:1 - | -LL | pub enum ElemDerived { - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: ...which immediately requires computing drop-check constraints for `ElemDerived` again -note: cycle used when computing drop-check constraints for `Elem` - --> $DIR/issue-72554.rs:11:1 - | -LL | pub enum Elem { - | ^^^^^^^^^^^^^ - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0072, E0391. -For more information about an error, try `rustc --explain E0072`. +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/infinite/infinite-struct.rs b/tests/ui/infinite/infinite-struct.rs index d784455824604..f08e10f6bdbc0 100644 --- a/tests/ui/infinite/infinite-struct.rs +++ b/tests/ui/infinite/infinite-struct.rs @@ -1,7 +1,5 @@ struct Take(Take); //~^ ERROR has infinite size -//~| ERROR cycle -//~| ERROR reached the recursion limit finding the struct tail for `Take` // check that we don't hang trying to find the tail of a recursive struct (#79437) fn foo() -> Take { diff --git a/tests/ui/infinite/infinite-struct.stderr b/tests/ui/infinite/infinite-struct.stderr index 0d1ec4989aa53..b6c72b1de4695 100644 --- a/tests/ui/infinite/infinite-struct.stderr +++ b/tests/ui/infinite/infinite-struct.stderr @@ -10,7 +10,7 @@ LL | struct Take(Box); | ++++ + error[E0072]: recursive type `Foo` has infinite size - --> $DIR/infinite-struct.rs:12:1 + --> $DIR/infinite-struct.rs:10:1 | LL | struct Foo { | ^^^^^^^^^^ @@ -22,25 +22,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | x: Bar>, | ++++ + -error: reached the recursion limit finding the struct tail for `Take` - --> $DIR/infinite-struct.rs:1:1 - | -LL | struct Take(Take); - | ^^^^^^^^^^^ - | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` - -error[E0391]: cycle detected when computing when `Take` needs drop - --> $DIR/infinite-struct.rs:1:1 - | -LL | struct Take(Take); - | ^^^^^^^^^^^ - | - = note: ...which immediately requires computing when `Take` needs drop again - = note: cycle used when computing whether `Take` needs drop - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0072, E0391. -For more information about an error, try `rustc --explain E0072`. +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/infinite/infinite-tag-type-recursion.rs b/tests/ui/infinite/infinite-tag-type-recursion.rs index 1b5cb55b4e4d1..87a9e08dd381a 100644 --- a/tests/ui/infinite/infinite-tag-type-recursion.rs +++ b/tests/ui/infinite/infinite-tag-type-recursion.rs @@ -1,5 +1,4 @@ enum MList { Cons(isize, MList), Nil } //~^ ERROR recursive type `MList` has infinite size -//~| ERROR cycle fn main() { let a = MList::Cons(10, MList::Cons(11, MList::Nil)); } diff --git a/tests/ui/infinite/infinite-tag-type-recursion.stderr b/tests/ui/infinite/infinite-tag-type-recursion.stderr index 8745224a45e13..4ca408260b84a 100644 --- a/tests/ui/infinite/infinite-tag-type-recursion.stderr +++ b/tests/ui/infinite/infinite-tag-type-recursion.stderr @@ -9,17 +9,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | enum MList { Cons(isize, Box), Nil } | ++++ + -error[E0391]: cycle detected when computing when `MList` needs drop - --> $DIR/infinite-tag-type-recursion.rs:1:1 - | -LL | enum MList { Cons(isize, MList), Nil } - | ^^^^^^^^^^ - | - = note: ...which immediately requires computing when `MList` needs drop again - = note: cycle used when computing whether `MList` needs drop - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0072, E0391. -For more information about an error, try `rustc --explain E0072`. +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/query-system/query-cycle-printing-issue-151226.rs b/tests/ui/query-system/query-cycle-printing-issue-151226.rs index 9d0a20737c9fa..551321619ddd0 100644 --- a/tests/ui/query-system/query-cycle-printing-issue-151226.rs +++ b/tests/ui/query-system/query-cycle-printing-issue-151226.rs @@ -1,8 +1,6 @@ struct A(std::sync::OnceLock); //~^ ERROR recursive type `A` has infinite size -//~| ERROR cycle detected when computing layout of `A<()>` static B: A<()> = todo!(); -//~^ ERROR cycle occurred during layout computation fn main() {} diff --git a/tests/ui/query-system/query-cycle-printing-issue-151226.stderr b/tests/ui/query-system/query-cycle-printing-issue-151226.stderr index 7e574b5911a39..bb05cf5f915d7 100644 --- a/tests/ui/query-system/query-cycle-printing-issue-151226.stderr +++ b/tests/ui/query-system/query-cycle-printing-issue-151226.stderr @@ -9,28 +9,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | struct A(Box>); | ++++ + -error[E0391]: cycle detected when computing layout of `A<()>` - | - = note: ...which requires computing layout of `std::sync::once_lock::OnceLock>`... - = note: ...which requires computing layout of `core::cell::UnsafeCell>>`... - = note: ...which requires computing layout of `core::mem::maybe_uninit::MaybeUninit>`... - = note: ...which requires computing layout of `core::mem::manually_drop::ManuallyDrop>`... - = note: ...which requires computing layout of `core::mem::maybe_dangling::MaybeDangling>`... - = note: ...which again requires computing layout of `A<()>`, completing the cycle -note: cycle used when checking that `B` is well-formed - --> $DIR/query-cycle-printing-issue-151226.rs:5:1 - | -LL | static B: A<()> = todo!(); - | ^^^^^^^^^^^^^^^ - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - -error[E0080]: a cycle occurred during layout computation - --> $DIR/query-cycle-printing-issue-151226.rs:5:1 - | -LL | static B: A<()> = todo!(); - | ^^^^^^^^^^^^^^^ evaluation of `B` failed here - -error: aborting due to 3 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0072, E0080, E0391. -For more information about an error, try `rustc --explain E0072`. +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/structs-enums/enum-rec/issue-17431-6.rs b/tests/ui/structs-enums/enum-rec/issue-17431-6.rs index a3b510848dcd3..c89b69d3c2f2e 100644 --- a/tests/ui/structs-enums/enum-rec/issue-17431-6.rs +++ b/tests/ui/structs-enums/enum-rec/issue-17431-6.rs @@ -2,7 +2,6 @@ use std::cell::UnsafeCell; enum Foo { X(UnsafeCell>) } //~^ ERROR recursive type `Foo` has infinite size -//~| ERROR cycle detected impl Foo { fn bar(self) {} } diff --git a/tests/ui/structs-enums/enum-rec/issue-17431-6.stderr b/tests/ui/structs-enums/enum-rec/issue-17431-6.stderr index b192593d266b7..8939b603c7985 100644 --- a/tests/ui/structs-enums/enum-rec/issue-17431-6.stderr +++ b/tests/ui/structs-enums/enum-rec/issue-17431-6.stderr @@ -9,17 +9,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | enum Foo { X(UnsafeCell>>) } | ++++ + -error[E0391]: cycle detected when computing when `Foo` needs drop - --> $DIR/issue-17431-6.rs:3:1 - | -LL | enum Foo { X(UnsafeCell>) } - | ^^^^^^^^ - | - = note: ...which immediately requires computing when `Foo` needs drop again - = note: cycle used when computing whether `Foo` needs drop - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0072, E0391. -For more information about an error, try `rustc --explain E0072`. +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/traits/issue-105231.rs b/tests/ui/traits/issue-105231.rs index 83c3158c106b6..9e47ded7c8c81 100644 --- a/tests/ui/traits/issue-105231.rs +++ b/tests/ui/traits/issue-105231.rs @@ -6,5 +6,4 @@ struct B(A>); trait Foo {} impl Foo for T where T: Send {} impl Foo for B {} -//~^ ERROR conflicting implementations of trait `Foo` for type `B` fn main() {} diff --git a/tests/ui/traits/issue-105231.stderr b/tests/ui/traits/issue-105231.stderr index b048548018a71..6732d4f5803c9 100644 --- a/tests/ui/traits/issue-105231.stderr +++ b/tests/ui/traits/issue-105231.stderr @@ -37,18 +37,6 @@ LL | struct B(A>); = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` = note: all type parameters must be used in a non-recursive way in order to constrain their variance -error[E0119]: conflicting implementations of trait `Foo` for type `B` - --> $DIR/issue-105231.rs:8:1 - | -LL | impl Foo for T where T: Send {} - | ------------------------------- first implementation here -LL | impl Foo for B {} - | ^^^^^^^^^^^^^^^^^^ conflicting implementation for `B` - | - = note: overflow evaluating the requirement `B: Send` - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_105231`) - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0072, E0119. -For more information about an error, try `rustc --explain E0072`. +For more information about this error, try `rustc --explain E0072`. diff --git a/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.rs b/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.rs index 8d291054365f9..d3a6ba94b68fb 100644 --- a/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.rs +++ b/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.rs @@ -1,4 +1,3 @@ -//~ ERROR: cycle detected //! Safe transmute did not handle cycle errors that could occur during //! layout computation. This test checks that we do not ICE in such //! situations (see #117491). diff --git a/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.stderr b/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.stderr index a96876a2c25a1..0b5689e1912f0 100644 --- a/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.stderr +++ b/tests/ui/transmutability/structs/repr/transmute_infinitely_recursive_type.stderr @@ -1,5 +1,5 @@ error[E0072]: recursive type `ExplicitlyPadded` has infinite size - --> $DIR/transmute_infinitely_recursive_type.rs:21:5 + --> $DIR/transmute_infinitely_recursive_type.rs:20:5 | LL | struct ExplicitlyPadded(ExplicitlyPadded); | ^^^^^^^^^^^^^^^^^^^^^^^ ---------------- recursive without indirection @@ -9,13 +9,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle LL | struct ExplicitlyPadded(Box); | ++++ + -error[E0391]: cycle detected when computing layout of `should_pad_explicitly_packed_field::ExplicitlyPadded` - | - = note: ...which immediately requires computing layout of `should_pad_explicitly_packed_field::ExplicitlyPadded` again - = note: cycle used when evaluating trait selection obligation `(): core::mem::transmutability::TransmuteFrom` - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0072, E0391. -For more information about an error, try `rustc --explain E0072`. +For more information about this error, try `rustc --explain E0072`. From ff3d308966724fb33303fd9a474027297a43f832 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 27 Feb 2026 17:38:59 +1100 Subject: [PATCH 2/2] Eliminate `Representability::Infinite`. This variant was a fallback value used to continue analysis after a `Representability` error, but it's no longer needed thanks to the previous commit. This means `Representability` can now be reduced to a unit type that exists just so `FromCycleError` can exist for the `representability` query. (There is potential for additional cleanups here, but those are beyond the scope of this PR.) This means the `representability`/`representability_adt_ty` queries no longer have a meaningful return value, i.e. they are check-only queries. So they now have a `check_` prefix added. And the `rtry!` macro is no longer needed. --- .../rustc_hir_analysis/src/check/wfcheck.rs | 2 +- compiler/rustc_middle/src/queries.rs | 17 ++-- compiler/rustc_middle/src/ty/adt.rs | 7 +- .../rustc_middle/src/ty/inhabitedness/mod.rs | 5 +- .../rustc_query_impl/src/from_cycle_error.rs | 4 +- .../rustc_ty_utils/src/representability.rs | 82 ++++++++++--------- compiler/rustc_ty_utils/src/ty.rs | 7 +- 7 files changed, 64 insertions(+), 60 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 0b6165c02baba..38025f74b2f69 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -997,7 +997,7 @@ fn check_type_defn<'tcx>( item: &hir::Item<'tcx>, all_sized: bool, ) -> Result<(), ErrorGuaranteed> { - let _ = tcx.representability(item.owner_id.def_id); + let _ = tcx.check_representability(item.owner_id.def_id); let adt_def = tcx.adt_def(item.owner_id); enter_wf_checking_ctxt(tcx, item.owner_id.def_id, |wfcx| { diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index 932d0855c6016..4c7d68ebd3e09 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -593,18 +593,23 @@ rustc_queries! { } /// Checks whether a type is representable or infinitely sized - query representability(key: LocalDefId) -> rustc_middle::ty::Representability { + query check_representability(key: LocalDefId) -> rustc_middle::ty::Representability { desc { "checking if `{}` is representable", tcx.def_path_str(key) } - // infinitely sized types will cause a cycle + // Infinitely sized types will cause a cycle. The custom `FromCycleError` impl for + // `Representability` will print a custom error about the infinite size and then abort + // compilation. (In the past we recovered and continued, but in practice that leads to + // confusing subsequent error messages about cycles that then abort.) cycle_delay_bug - // we don't want recursive representability calls to be forced with + // We don't want recursive representability calls to be forced with // incremental compilation because, if a cycle occurs, we need the - // entire cycle to be in memory for diagnostics + // entire cycle to be in memory for diagnostics. This means we can't + // use `ensure_ok()` with this query. anon } - /// An implementation detail for the `representability` query - query representability_adt_ty(key: Ty<'tcx>) -> rustc_middle::ty::Representability { + /// An implementation detail for the `check_representability` query. See that query for more + /// details, particularly on the modifiers. + query check_representability_adt_ty(key: Ty<'tcx>) -> rustc_middle::ty::Representability { desc { "checking if `{}` is representable", key } cycle_delay_bug anon diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index c141eb0311dcf..6a51ea4deffee 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -741,8 +741,7 @@ impl<'tcx> AdtDef<'tcx> { } } +/// This type exists just so a `FromCycleError` impl can be made for the `check_representability` +/// query. #[derive(Clone, Copy, Debug, HashStable)] -pub enum Representability { - Representable, - Infinite(ErrorGuaranteed), -} +pub struct Representability; diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs index 5c4c1733be29e..b454689e243d2 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs @@ -61,10 +61,9 @@ pub(crate) fn provide(providers: &mut Providers) { /// requires calling [`InhabitedPredicate::instantiate`] fn inhabited_predicate_adt(tcx: TyCtxt<'_>, def_id: DefId) -> InhabitedPredicate<'_> { if let Some(def_id) = def_id.as_local() { - if matches!(tcx.representability(def_id), ty::Representability::Infinite(_)) { - return InhabitedPredicate::True; - } + let _ = tcx.check_representability(def_id); } + let adt = tcx.adt_def(def_id); InhabitedPredicate::any( tcx, diff --git a/compiler/rustc_query_impl/src/from_cycle_error.rs b/compiler/rustc_query_impl/src/from_cycle_error.rs index 328bd4a02c8fd..eb6942ba491ff 100644 --- a/compiler/rustc_query_impl/src/from_cycle_error.rs +++ b/compiler/rustc_query_impl/src/from_cycle_error.rs @@ -95,7 +95,7 @@ impl<'tcx> FromCycleError<'tcx> for Representability { let mut item_and_field_ids = Vec::new(); let mut representable_ids = FxHashSet::default(); for info in &cycle_error.cycle { - if info.frame.dep_kind == DepKind::representability + if info.frame.dep_kind == DepKind::check_representability && let Some(field_id) = info.frame.def_id && let Some(field_id) = field_id.as_local() && let Some(DefKind::Field) = info.frame.info.def_kind @@ -109,7 +109,7 @@ impl<'tcx> FromCycleError<'tcx> for Representability { } } for info in &cycle_error.cycle { - if info.frame.dep_kind == DepKind::representability_adt_ty + if info.frame.dep_kind == DepKind::check_representability_adt_ty && let Some(def_id) = info.frame.def_id_for_ty_in_cycle && let Some(def_id) = def_id.as_local() && !item_and_field_ids.iter().any(|&(id, _)| id == def_id) diff --git a/compiler/rustc_ty_utils/src/representability.rs b/compiler/rustc_ty_utils/src/representability.rs index 33d334092ba9c..1814e7604a2d1 100644 --- a/compiler/rustc_ty_utils/src/representability.rs +++ b/compiler/rustc_ty_utils/src/representability.rs @@ -6,69 +6,71 @@ use rustc_middle::ty::{self, Representability, Ty, TyCtxt}; use rustc_span::def_id::LocalDefId; pub(crate) fn provide(providers: &mut Providers) { - *providers = - Providers { representability, representability_adt_ty, params_in_repr, ..*providers }; -} - -macro_rules! rtry { - ($e:expr) => { - match $e { - e @ Representability::Infinite(_) => return e, - Representability::Representable => {} - } + *providers = Providers { + check_representability, + check_representability_adt_ty, + params_in_repr, + ..*providers }; } -fn representability(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Representability { +fn check_representability(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Representability { match tcx.def_kind(def_id) { DefKind::Struct | DefKind::Union | DefKind::Enum => { for variant in tcx.adt_def(def_id).variants() { for field in variant.fields.iter() { - rtry!(tcx.representability(field.did.expect_local())); + let _ = tcx.check_representability(field.did.expect_local()); } } - Representability::Representable } - DefKind::Field => representability_ty(tcx, tcx.type_of(def_id).instantiate_identity()), + DefKind::Field => { + check_representability_ty(tcx, tcx.type_of(def_id).instantiate_identity()); + } def_kind => bug!("unexpected {def_kind:?}"), } + Representability } -fn representability_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Representability { +fn check_representability_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) { match *ty.kind() { - ty::Adt(..) => tcx.representability_adt_ty(ty), + // This one must be a query rather than a vanilla `check_representability_adt_ty` call. See + // the comment on `check_representability_adt_ty` below for why. + ty::Adt(..) => { + let _ = tcx.check_representability_adt_ty(ty); + } // FIXME(#11924) allow zero-length arrays? - ty::Array(ty, _) => representability_ty(tcx, ty), + ty::Array(ty, _) => { + check_representability_ty(tcx, ty); + } ty::Tuple(tys) => { for ty in tys { - rtry!(representability_ty(tcx, ty)); + check_representability_ty(tcx, ty); } - Representability::Representable } - _ => Representability::Representable, + _ => {} } } -/* -The reason for this being a separate query is very subtle: -Consider this infinitely sized struct: `struct Foo(Box, Bar)`: -When calling representability(Foo), a query cycle will occur: - representability(Foo) - -> representability_adt_ty(Bar) - -> representability(Foo) -For the diagnostic output (in `Value::from_cycle_error`), we want to detect that -the `Foo` in the *second* field of the struct is culpable. This requires -traversing the HIR of the struct and calling `params_in_repr(Bar)`. But we can't -call params_in_repr for a given type unless it is known to be representable. -params_in_repr will cycle/panic on infinitely sized types. Looking at the query -cycle above, we know that `Bar` is representable because -representability_adt_ty(Bar<..>) is in the cycle and representability(Bar) is -*not* in the cycle. -*/ -fn representability_adt_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Representability { +// The reason for this being a separate query is very subtle. Consider this +// infinitely sized struct: `struct Foo(Box, Bar)`. When calling +// check_representability(Foo), a query cycle will occur: +// +// check_representability(Foo) +// -> check_representability_adt_ty(Bar) +// -> check_representability(Foo) +// +// For the diagnostic output (in `Value::from_cycle_error`), we want to detect +// that the `Foo` in the *second* field of the struct is culpable. This +// requires traversing the HIR of the struct and calling `params_in_repr(Bar)`. +// But we can't call params_in_repr for a given type unless it is known to be +// representable. params_in_repr will cycle/panic on infinitely sized types. +// Looking at the query cycle above, we know that `Bar` is representable +// because `check_representability_adt_ty(Bar<..>)` is in the cycle and +// `check_representability(Bar)` is *not* in the cycle. +fn check_representability_adt_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Representability { let ty::Adt(adt, args) = ty.kind() else { bug!("expected adt") }; if let Some(def_id) = adt.did().as_local() { - rtry!(tcx.representability(def_id)); + let _ = tcx.check_representability(def_id); } // At this point, we know that the item of the ADT type is representable; // but the type parameters may cause a cycle with an upstream type @@ -76,11 +78,11 @@ fn representability_adt_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Representab for (i, arg) in args.iter().enumerate() { if let ty::GenericArgKind::Type(ty) = arg.kind() { if params_in_repr.contains(i as u32) { - rtry!(representability_ty(tcx, ty)); + check_representability_ty(tcx, ty); } } } - Representability::Representable + Representability } fn params_in_repr(tcx: TyCtxt<'_>, def_id: LocalDefId) -> DenseBitSet { diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index d6a29aba22b90..78f3a19228870 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -116,11 +116,10 @@ fn adt_sizedness_constraint<'tcx>( tcx: TyCtxt<'tcx>, (def_id, sizedness): (DefId, SizedTraitKind), ) -> Option>> { - if let Some(def_id) = def_id.as_local() - && let ty::Representability::Infinite(_) = tcx.representability(def_id) - { - return None; + if let Some(def_id) = def_id.as_local() { + let _ = tcx.check_representability(def_id); } + let def = tcx.adt_def(def_id); if !def.is_struct() {