From: Philip Herron <herron.phi...@googlemail.com>

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 | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc 
b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
index 35c9b0a6a2d..fccc53ed6c2 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
@@ -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 ());
 }
 
-- 
2.49.0

Reply via email to