From: Philip Herron <philip.her...@embecosm.com>

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
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust

Reply via email to