public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
From: Thomas Schwinge <tschwinge@gcc.gnu.org>
To: gcc-cvs@gcc.gnu.org
Subject: [gcc/devel/rust/master] Add check for recursive trait cycles
Date: Wed, 19 Oct 2022 19:45:33 +0000 (GMT)	[thread overview]
Message-ID: <20221019194533.7CD1D385828E@sourceware.org> (raw)

https://gcc.gnu.org/g:0a52177612f6e855732c6ded77a04ba40dfb0d19

commit 0a52177612f6e855732c6ded77a04ba40dfb0d19
Author: Philip Herron <philip.herron@embecosm.com>
Date:   Mon Oct 17 11:35:26 2022 +0100

    Add check for recursive trait cycles
    
    This adds a new RAII style TraitQueryGuard so that we can manage the query
    lifetime when resolving a trait. This adds in a DefId into a set when we
    begin to resolve and then finally removes it when completed. This allows
    us to add in a check at the start if this DefId is already within the set
    which means this is a trait cycle.
    
    Fixes #1589

Diff:
---
 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(-)

diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
index cc23fe22d7f..6bd3cc1a9e9 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 f85585bccf6..de3467b27ce 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 }

                 reply	other threads:[~2022-10-19 19:45 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221019194533.7CD1D385828E@sourceware.org \
    --to=tschwinge@gcc.gnu.org \
    --cc=gcc-cvs@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).