]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: Fix cyclical projection to placeholder
authorPhilip Herron <herron.philip@googlemail.com>
Sat, 21 Jun 2025 13:22:04 +0000 (14:22 +0100)
committerArthur Cohen <arthur.cohen@embecosm.com>
Tue, 5 Aug 2025 14:36:50 +0000 (16:36 +0200)
Prevent infinite loops when projecting associated types by properly
handling cyclical references with placeholder types.

gcc/rust/ChangeLog:

* typecheck/rust-hir-trait-resolve.cc: Add cyclical projection
protection.

gcc/rust/typecheck/rust-hir-trait-resolve.cc

index 35c9b0a6a2d32876d894f3b4b6d5ee8907e556dc..fccc53ed6c2dd0710294d48d798cb3473e26c353 100644 (file)
@@ -444,11 +444,27 @@ TraitItemReference::associated_type_set (TyTy::BaseType *ty) const
 {
   rust_assert (get_trait_item_type () == TraitItemType::TYPE);
 
+  // this isnt super safe there are cases like the FnTraits where the type is
+  // set to the impls placeholder associated type. For example
+  //
+  // type Output = F::Output; -- see the fn trait impls in libcore
+  //
+  // then this projection ends up resolving back to this placeholder so it just
+  // ends up being cyclical
+
   TyTy::BaseType *item_ty = get_tyty ();
   rust_assert (item_ty->get_kind () == TyTy::TypeKind::PLACEHOLDER);
   TyTy::PlaceholderType *placeholder
     = static_cast<TyTy::PlaceholderType *> (item_ty);
 
+  if (ty->is<TyTy::ProjectionType> ())
+    {
+      const auto &projection = *static_cast<const TyTy::ProjectionType *> (ty);
+      const auto resolved = projection.get ();
+      if (resolved == item_ty)
+       return;
+    }
+
   placeholder->set_associated_type (ty->get_ty_ref ());
 }