aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-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 cc23fe2..6bd3cc1 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 f85585b..de3467b 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 }