about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <476013+matthiaskrgr@users.noreply.github.com>2025-07-17 10:41:45 +0200
committerGitHub <noreply@github.com>2025-07-17 10:41:45 +0200
commitf78cc420323c6ee6f818cf236680136c164035ca (patch)
treea48cebf721819bf1dd245b80d31941ff012c7b7a
parent465ae9432812040a80b7c22c5a1c020663757e0f (diff)
parent28af50075724bd1fa94b7e147b1e230534a70ab9 (diff)
downloadrust-f78cc420323c6ee6f818cf236680136c164035ca.tar.gz
rust-f78cc420323c6ee6f818cf236680136c164035ca.zip
Rollup merge of #143793 - fmease:lta-opaq-inf-recur, r=oli-obk
Opaque type collection: Guard against endlessly recursing free alias types

See test description for technical details.

Fixes https://github.com/rust-lang/rust/issues/131994.

r? oli-obk (sry, your queue is large, so no rush & feel free to reassign)
-rw-r--r--compiler/rustc_ty_utils/src/opaque_types.rs11
-rw-r--r--tests/ui/lazy-type-alias/opaq-ty-collection-infinite-recur.rs18
-rw-r--r--tests/ui/lazy-type-alias/opaq-ty-collection-infinite-recur.stderr11
3 files changed, 36 insertions, 4 deletions
diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs
index 3b313edea6f..4a7263d0ccd 100644
--- a/compiler/rustc_ty_utils/src/opaque_types.rs
+++ b/compiler/rustc_ty_utils/src/opaque_types.rs
@@ -223,7 +223,10 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
             }
             // Skips type aliases, as they are meant to be transparent.
             // FIXME(type_alias_impl_trait): can we require mentioning nested type aliases explicitly?
-            ty::Alias(ty::Free, alias_ty) if alias_ty.def_id.is_local() => {
+            ty::Alias(ty::Free, alias_ty) if let Some(def_id) = alias_ty.def_id.as_local() => {
+                if !self.seen.insert(def_id) {
+                    return;
+                }
                 self.tcx
                     .type_of(alias_ty.def_id)
                     .instantiate(self.tcx, alias_ty.args)
@@ -256,16 +259,16 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
                                 return;
                             }
 
-                            let impl_args = alias_ty.args.rebase_onto(
+                            let alias_args = alias_ty.args.rebase_onto(
                                 self.tcx,
                                 impl_trait_ref.def_id,
                                 ty::GenericArgs::identity_for_item(self.tcx, parent),
                             );
 
-                            if self.tcx.check_args_compatible(assoc.def_id, impl_args) {
+                            if self.tcx.check_args_compatible(assoc.def_id, alias_args) {
                                 self.tcx
                                     .type_of(assoc.def_id)
-                                    .instantiate(self.tcx, impl_args)
+                                    .instantiate(self.tcx, alias_args)
                                     .visit_with(self);
                                 return;
                             } else {
diff --git a/tests/ui/lazy-type-alias/opaq-ty-collection-infinite-recur.rs b/tests/ui/lazy-type-alias/opaq-ty-collection-infinite-recur.rs
new file mode 100644
index 00000000000..34803c8c103
--- /dev/null
+++ b/tests/ui/lazy-type-alias/opaq-ty-collection-infinite-recur.rs
@@ -0,0 +1,18 @@
+// The opaque type collector used to expand free alias types (in situ) without guarding against
+// endlessly recursing aliases which lead to the compiler overflowing its stack in certain
+// situations.
+//
+// In most situations we wouldn't even reach the collector when there's an overflow because we
+// would've already bailed out early during the item's wfcheck due to the normalization failure.
+//
+// In the case below however, while collecting the opaque types defined by the AnonConst, we
+// descend into its nested items (here: type alias `Recur`) to acquire their opaque types --
+// meaning we get there before we wfcheck `Recur`.
+//
+// issue: <https://github.com/rust-lang/rust/issues/131994>
+#![feature(lazy_type_alias)]
+#![expect(incomplete_features)]
+
+struct Hold([(); { type Recur = Recur; 0 }]); //~ ERROR overflow normalizing the type alias `Recur`
+
+fn main() {}
diff --git a/tests/ui/lazy-type-alias/opaq-ty-collection-infinite-recur.stderr b/tests/ui/lazy-type-alias/opaq-ty-collection-infinite-recur.stderr
new file mode 100644
index 00000000000..e93fcd03a96
--- /dev/null
+++ b/tests/ui/lazy-type-alias/opaq-ty-collection-infinite-recur.stderr
@@ -0,0 +1,11 @@
+error[E0275]: overflow normalizing the type alias `Recur`
+  --> $DIR/opaq-ty-collection-infinite-recur.rs:16:20
+   |
+LL | struct Hold([(); { type Recur = Recur; 0 }]);
+   |                    ^^^^^^^^^^
+   |
+   = note: in case this is a recursive type alias, consider using a struct, enum, or union instead
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0275`.