[gccrs COMMIT 03/17] gccrs: Add method resolution probe support to take a trait to filter

gerris.rs@gmail.com gerris.rs@gmail.com
Sun Aug 30 21:45:59 GMT 2026


From: Philip Herron <herron.philip@googlemail.com>

This means we can do some pre filtering instead of scanning the crate.

gcc/rust/ChangeLog:

	* typecheck/rust-hir-dot-operator.cc (MethodResolver::MethodResolver): new optional filter
	(MethodResolver::Probe): likewise
	(MethodResolver::try_select_predicate_candidates): likewise
	(MethodResolver::select): likewise
	* typecheck/rust-hir-dot-operator.h: likewise
	* typecheck/rust-hir-type-check-expr.cc: pass lang item trait
	* util/rust-hir-map.cc: new helper to scan implblocks
	* util/rust-hir-map.h: likewise

Signed-off-by: Philip Herron <herron.philip@googlemail.com>
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.


Commit on github: https://github.com/Rust-GCC/gccrs/commit/daf38279d19e57bde0ba50eb7d458fc5bf783c73

The commit has NOT been mentioned in any issue.

The commit has been mentioned in the following pull-request(s):
 - https://github.com/Rust-GCC/gccrs/pull/4816

 gcc/rust/typecheck/rust-hir-dot-operator.cc   | 34 ++++++++++++++-----
 gcc/rust/typecheck/rust-hir-dot-operator.h    |  7 ++--
 .../typecheck/rust-hir-type-check-expr.cc     |  2 +-
 gcc/rust/util/rust-hir-map.cc                 | 13 +++++++
 gcc/rust/util/rust-hir-map.h                  |  4 +++
 5 files changed, 48 insertions(+), 12 deletions(-)

diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.cc b/gcc/rust/typecheck/rust-hir-dot-operator.cc
index d1095d553..f74005e1e 100644
--- a/gcc/rust/typecheck/rust-hir-dot-operator.cc
+++ b/gcc/rust/typecheck/rust-hir-dot-operator.cc
@@ -27,16 +27,18 @@ namespace Rust {
 namespace Resolver {
 
 MethodResolver::MethodResolver (bool autoderef_flag,
-				const HIR::PathIdentSegment &segment_name)
-  : AutoderefCycle (autoderef_flag), segment_name (segment_name), result ()
+				const HIR::PathIdentSegment &segment_name,
+				const HIR::Trait *specified_trait)
+  : AutoderefCycle (autoderef_flag), segment_name (segment_name),
+    specified_trait (specified_trait), result ()
 {}
 
 std::set<MethodCandidate>
 MethodResolver::Probe (TyTy::BaseType *receiver,
 		       const HIR::PathIdentSegment &segment_name,
-		       bool autoderef_flag)
+		       bool autoderef_flag, const HIR::Trait *specified_trait)
 {
-  MethodResolver resolver (autoderef_flag, segment_name);
+  MethodResolver resolver (autoderef_flag, segment_name, specified_trait);
   resolver.cycle (receiver);
   return resolver.result;
 }
@@ -203,8 +205,7 @@ MethodResolver::assemble_trait_impl_candidates (
   bool receiver_is_raw_ptr = raw->get_kind () == TyTy::TypeKind::POINTER;
   bool receiver_is_ref = raw->get_kind () == TyTy::TypeKind::REF;
 
-  mappings.iterate_impl_blocks ([&] (HirId id,
-				     HIR::ImplBlock *impl) mutable -> bool {
+  auto process_impl = [&] (HirId id, HIR::ImplBlock *impl) mutable -> bool {
     bool is_trait_impl = impl->has_trait_ref ();
     if (!is_trait_impl)
       return true;
@@ -300,7 +301,13 @@ MethodResolver::assemble_trait_impl_candidates (
     trait_candidates.emplace_back (func, trait, fnty, trait_ref, item_ref);
 
     return true;
-  });
+  };
+
+  if (specified_trait == nullptr)
+    mappings.iterate_impl_blocks (process_impl);
+  else
+    mappings.iterate_trait_impl_blocks (
+      specified_trait->get_mappings ().get_nodeid (), process_impl);
 }
 
 bool
@@ -309,6 +316,14 @@ MethodResolver::try_select_predicate_candidates (TyTy::BaseType &receiver)
   bool found_possible_candidate = false;
   for (const auto &predicate : predicate_items)
     {
+      if (specified_trait != nullptr)
+	{
+	  const TraitReference *parent = predicate.lookup.get_parent ()->get ();
+	  if (parent->get_mappings ().get_nodeid ()
+	      != specified_trait->get_mappings ().get_nodeid ())
+	    continue;
+	}
+
       const TyTy::FnType *fn = predicate.fntype;
       if (!fn->is_method ())
 	continue;
@@ -434,8 +449,9 @@ MethodResolver::select (TyTy::BaseType &receiver)
 	      segment_name.to_string ().c_str ());
 
   // Assemble candidates
-  std::vector<impl_item_candidate> inherent_impl_fns
-    = assemble_inherent_impl_candidates (receiver);
+  std::vector<impl_item_candidate> inherent_impl_fns;
+  if (specified_trait == nullptr)
+    inherent_impl_fns = assemble_inherent_impl_candidates (receiver);
   std::vector<impl_item_candidate> trait_impl_fns;
   std::vector<trait_item_candidate> trait_fns;
   assemble_trait_impl_candidates (receiver, trait_impl_fns, trait_fns);
diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.h b/gcc/rust/typecheck/rust-hir-dot-operator.h
index 31160ed90..79c5db1c0 100644
--- a/gcc/rust/typecheck/rust-hir-dot-operator.h
+++ b/gcc/rust/typecheck/rust-hir-dot-operator.h
@@ -59,7 +59,8 @@ public:
 
   static std::set<MethodCandidate>
   Probe (TyTy::BaseType *receiver, const HIR::PathIdentSegment &segment_name,
-	 bool autoderef_flag = false);
+	 bool autoderef_flag = false,
+	 const HIR::Trait *specified_trait = nullptr);
 
   static std::set<MethodCandidate>
   Select (std::set<MethodCandidate> &candidates, TyTy::BaseType *receiver,
@@ -99,7 +100,8 @@ public:
 
 protected:
   MethodResolver (bool autoderef_flag,
-		  const HIR::PathIdentSegment &segment_name);
+		  const HIR::PathIdentSegment &segment_name,
+		  const HIR::Trait *specified_trait);
 
   void try_hook (const TyTy::BaseType &r) override;
 
@@ -131,6 +133,7 @@ private:
 private:
   // search
   const HIR::PathIdentSegment &segment_name;
+  const HIR::Trait *specified_trait;
   std::vector<MethodResolver::predicate_candidate> predicate_items;
 
   // mutable fields
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
index 8ba1df7d2..1c24c7c93 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -2046,7 +2046,7 @@ TypeCheckExpr::resolve_operator_overload (
   auto segment = specified_segment.is_error ()
 		   ? HIR::PathIdentSegment (associated_item_name)
 		   : specified_segment;
-  auto candidates = MethodResolver::Probe (lhs, segment);
+  auto candidates = MethodResolver::Probe (lhs, segment, false, &trait);
 
   // remove any recursive candidates
   std::set<MethodCandidate> resolved_candidates;
diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc
index d7d0cc87c..fc6a64307 100644
--- a/gcc/rust/util/rust-hir-map.cc
+++ b/gcc/rust/util/rust-hir-map.cc
@@ -854,6 +854,19 @@ Mappings::iterate_trait_impl_items (
       }
 }
 
+void
+Mappings::iterate_trait_impl_blocks (
+  NodeId trait_node_id, std::function<bool (HirId, HIR::ImplBlock *)> cb)
+{
+  auto trait_impls = hirTraitImplMappings.find (trait_node_id);
+  if (trait_impls == hirTraitImplMappings.end ())
+    return;
+
+  for (auto *impl : trait_impls->second)
+    if (!cb (impl->get_mappings ().get_hirid (), impl))
+      return;
+}
+
 void
 Mappings::iterate_impl_blocks (std::function<bool (HirId, HIR::ImplBlock *)> cb)
 {
diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h
index 2f7431a00..bfe04f0bc 100644
--- a/gcc/rust/util/rust-hir-map.h
+++ b/gcc/rust/util/rust-hir-map.h
@@ -214,6 +214,10 @@ public:
     NodeId trait_node_id,
     std::function<bool (HirId, HIR::ImplItem *, HIR::ImplBlock *)> cb);
 
+  void
+  iterate_trait_impl_blocks (NodeId trait_node_id,
+			     std::function<bool (HirId, HIR::ImplBlock *)> cb);
+
   void iterate_impl_blocks (std::function<bool (HirId, HIR::ImplBlock *)> cb);
 
   void iterate_trait_items (
-- 
2.55.0



More information about the Gcc-rust mailing list