Recursive const blocks containing trait implementations previously caused
an assertion failure (ICE) because the compiler re-visited existing IDs.
This patch adds a check to return early if the ID exists, enabling
graceful handling of recursion.
Fixes Rust-GCC/gccrs#4166
gcc/rust/ChangeLog:
* typecheck/rust-typecheck-context.cc (insert_associated_trait_impl):
Prevent ICE by checking for existing ID.
* typecheck/rust-hir-type-check.h: Update declarations.
gcc/testsuite/ChangeLog:
* rust/compile/issue-4166.rs: New test.
Signed-off-by: Harishankar <harishankarpp7@gmail.com>
void insert_trait_reference (DefId id, TraitReference &&ref);
bool lookup_trait_reference (DefId id, TraitReference **ref);
- void insert_associated_trait_impl (HirId id,
+ bool insert_associated_trait_impl (HirId id,
AssociatedImplTrait &&associated);
bool lookup_associated_trait_impl (HirId id,
AssociatedImplTrait **associated);
return true;
}
-void
+bool
TypeCheckContext::insert_associated_trait_impl (
HirId id, AssociatedImplTrait &&associated)
{
- rust_assert (associated_impl_traits.find (id)
- == associated_impl_traits.end ());
+ auto it = associated_impl_traits.find (id);
+ if (it != associated_impl_traits.end ())
+ {
+ return false;
+ }
associated_impl_traits.emplace (id, std::move (associated));
+ return true;
}
bool
--- /dev/null
+
+pub trait Foo {
+ type Bar;
+ fn foo(bar: Self::bar); // { dg-error "failed to resolve path segment using an impl Probe" }
+}
+
+pub struct FooImpl;
+
+const foo_impl: () = {
+ impl Foo for FooImpl {
+ type Bar = ();
+ fn foo(_bar: Self::Bar) { // { dg-error "method .foo. has an incompatible type|mismatched types" }
+ // This is the recursive reference that used to cause the ICE
+ let () = foo_impl;
+ }
+ }
+};
+
+fn main() {}
\ No newline at end of file