From: Philip Herron <[email protected]>
gcc/rust/ChangeLog:
* typecheck/rust-hir-trait-resolve.cc (TraitResolver::resolve_trait):
Check if a
trait query is currently in progress.
* typecheck/rust-hir-type-check.h (class TraitQueryGuard): Add helpers
around
checking for trait queries and inserting them.
gcc/testsuite/ChangeLog:
* rust/compile/issue-1589.rs: New test.
---
gcc/rust/typecheck/rust-hir-trait-resolve.cc | 12 +++++++-
gcc/rust/typecheck/rust-hir-type-check.h | 29 ++++++++++++++++++++
gcc/testsuite/rust/compile/issue-1589.rs | 5 ++++
3 files changed, 45 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/rust/compile/issue-1589.rs
diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc
b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
index 1b0bcaac79d..2ec9b2ef83e 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
@@ -141,6 +141,14 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference)
return tref;
}
+ DefId trait_id = trait_reference->get_mappings ().get_defid ();
+ if (context->trait_query_in_progress (trait_id))
+ {
+ rust_error_at (trait_reference->get_locus (), "trait cycle detected");
+ return &TraitReference::error_node ();
+ }
+
+ TraitQueryGuard guard (trait_id);
TyTy::BaseType *self = nullptr;
std::vector<TyTy::SubstitutionParamMapping> substitutions;
for (auto &generic_param : trait_reference->get_generic_params ())
@@ -201,8 +209,10 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference)
HIR::TraitBound *b
= static_cast<HIR::TraitBound *> (bound.get ());
- // FIXME this might be recursive we need a check for that
auto predicate = get_predicate_from_bound (b->get_path ());
+ if (predicate.is_error ())
+ return &TraitReference::error_node ();
+
specified_bounds.push_back (predicate);
super_traits.push_back (predicate.get ());
}
diff --git a/gcc/rust/typecheck/rust-hir-type-check.h
b/gcc/rust/typecheck/rust-hir-type-check.h
index a1dd8052246..2b47c6738b5 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.h
+++ b/gcc/rust/typecheck/rust-hir-type-check.h
@@ -381,6 +381,19 @@ public:
return querys_in_progress.find (id) != querys_in_progress.end ();
}
+ void insert_trait_query (DefId id) { trait_queries_in_progress.insert (id); }
+
+ void trait_query_completed (DefId id)
+ {
+ trait_queries_in_progress.erase (id);
+ }
+
+ bool trait_query_in_progress (DefId id) const
+ {
+ return trait_queries_in_progress.find (id)
+ != trait_queries_in_progress.end ();
+ }
+
private:
TypeCheckContext ();
@@ -418,6 +431,7 @@ private:
// query context lookups
std::set<HirId> querys_in_progress;
+ std::set<DefId> trait_queries_in_progress;
};
class TypeResolution
@@ -426,6 +440,21 @@ public:
static void Resolve (HIR::Crate &crate);
};
+class TraitQueryGuard
+{
+public:
+ TraitQueryGuard (DefId id) : id (id), ctx (*TypeCheckContext::get ())
+ {
+ ctx.insert_trait_query (id);
+ }
+
+ ~TraitQueryGuard () { ctx.trait_query_completed (id); }
+
+private:
+ DefId id;
+ TypeCheckContext &ctx;
+};
+
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/testsuite/rust/compile/issue-1589.rs
b/gcc/testsuite/rust/compile/issue-1589.rs
new file mode 100644
index 00000000000..79a5866e4af
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1589.rs
@@ -0,0 +1,5 @@
+pub trait A: B {}
+// { dg-error "trait cycle detected" "" { target *-*-* } .-1 }
+
+pub trait B: A {}
+// { dg-error "trait cycle detected" "" { target *-*-* } .-1 }
--
2.39.1
--
Gcc-rust mailing list
[email protected]
https://gcc.gnu.org/mailman/listinfo/gcc-rust