aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2022-10-17 11:35:26 +0100
committerArthur Cohen <arthur.cohen@embecosm.com>2023-02-21 12:36:36 +0100
commit643ec1c253d9fb3c915824dc3aa1f6b60e8d43f1 (patch)
treed5a13f6060059166ffc0507eb8634cbc7022c4b4
parentec28fdb6aad31f5262f8c3e29ec751b41cc3786e (diff)
downloadgcc-643ec1c253d9fb3c915824dc3aa1f6b60e8d43f1.zip
gcc-643ec1c253d9fb3c915824dc3aa1f6b60e8d43f1.tar.gz
gcc-643ec1c253d9fb3c915824dc3aa1f6b60e8d43f1.tar.bz2
gccrs: Add check for recursive trait cycles
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.
-rw-r--r--gcc/rust/typecheck/rust-hir-trait-resolve.cc12
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.h29
-rw-r--r--gcc/testsuite/rust/compile/issue-1589.rs5
3 files changed, 45 insertions, 1 deletions
diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
index 1b0bcaa..2ec9b2e 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 a1dd805..2b47c67 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 0000000..79a5866
--- /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 }