From: Philip Herron <[email protected]>
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