[gccrs COMMIT 2/5] gccrs: Improve method resolution to use seperate indexes for impl's

gerris.rs@gmail.com gerris.rs@gmail.com
Sun Sep 6 19:15:24 GMT 2026


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

gcc/rust/ChangeLog:

	* typecheck/rust-hir-dot-operator.cc (MethodResolver::select): use sperate index
	* util/rust-hir-map.cc (Mappings::insert_hir_impl_block): new indexes
	* 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/4d67061241ac10b7a38b12daaa2327cdcc7a42c1

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/4847

 gcc/rust/typecheck/rust-hir-dot-operator.cc | 169 ++++++++++----------
 gcc/rust/util/rust-hir-map.cc               |   4 +
 gcc/rust/util/rust-hir-map.h                |  18 +++
 3 files changed, 106 insertions(+), 85 deletions(-)

diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.cc b/gcc/rust/typecheck/rust-hir-dot-operator.cc
index e42c4b90a..a2ecb2649 100644
--- a/gcc/rust/typecheck/rust-hir-dot-operator.cc
+++ b/gcc/rust/typecheck/rust-hir-dot-operator.cc
@@ -123,87 +123,88 @@ MethodResolver::assemble_inherent_impl_candidates (
   bool receiver_is_raw_ptr = raw->get_kind () == TyTy::TypeKind::POINTER;
   bool receiver_is_ref = raw->get_kind () == TyTy::TypeKind::REF;
 
-  // Assemble inherent impl items (non-trait impl blocks)
-  mappings.iterate_impl_items ([&] (HirId id, HIR::ImplItem *item,
-				    HIR::ImplBlock *impl) mutable -> bool {
-    bool is_trait_impl = impl->has_trait_ref ();
-    if (is_trait_impl)
-      return true;
+  mappings.iterate_inherent_impl_blocks (
+    [&] (HirId, HIR::ImplBlock *impl) mutable -> bool {
+      for (auto &impl_item : impl->get_impl_items ())
+	{
+	  HIR::ImplItem *item = impl_item.get ();
+	  bool is_fn = item->get_impl_item_type ()
+		       == HIR::ImplItem::ImplItemType::FUNCTION;
+	  if (!is_fn)
+	    continue;
 
-    bool is_fn
-      = item->get_impl_item_type () == HIR::ImplItem::ImplItemType::FUNCTION;
-    if (!is_fn)
-      return true;
+	  HIR::Function *func = static_cast<HIR::Function *> (item);
+	  if (!func->is_method ())
+	    continue;
 
-    HIR::Function *func = static_cast<HIR::Function *> (item);
-    if (!func->is_method ())
-      return true;
+	  bool name_matches = func->get_function_name ().as_string ().compare (
+				segment_name.to_string ())
+			      == 0;
+	  if (!name_matches)
+	    continue;
 
-    bool name_matches = func->get_function_name ().as_string ().compare (
-			  segment_name.to_string ())
-			== 0;
-    if (!name_matches)
-      return true;
+	  TyTy::BaseType *impl_self
+	    = TypeCheckItem::ResolveImplBlockSelf (*impl);
 
-    TyTy::BaseType *impl_self = TypeCheckItem::ResolveImplBlockSelf (*impl);
+	  if (impl_self == nullptr
+	      || impl_self->get_kind () == TyTy::TypeKind::ERROR)
+	    continue;
 
-    if (impl_self == nullptr || impl_self->get_kind () == TyTy::TypeKind::ERROR)
-      return true;
+	  if (receiver.get_kind () == TyTy::TypeKind::ADT
+	      && impl_self->get_kind () == TyTy::TypeKind::ADT)
+	    {
+	      const auto &receiver_adt
+		= static_cast<const TyTy::ADTType &> (receiver);
+	      const auto &impl_adt
+		= static_cast<const TyTy::ADTType &> (*impl_self);
+	      if (receiver_adt.get_id () != impl_adt.get_id ())
+		continue;
+	    }
 
-    if (receiver.get_kind () == TyTy::TypeKind::ADT
-	&& impl_self->get_kind () == TyTy::TypeKind::ADT)
-      {
-	const auto &receiver_adt
-	  = static_cast<const TyTy::ADTType &> (receiver);
-	const auto &impl_adt = static_cast<const TyTy::ADTType &> (*impl_self);
-	if (receiver_adt.get_id () != impl_adt.get_id ())
-	  return true;
-      }
+	  // see:
+	  // https://gcc-rust.zulipchat.com/#narrow/stream/266897-general/topic/Method.20Resolution/near/338646280
+	  // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/method/probe.rs#L650-L660
+	  bool impl_self_is_ptr
+	    = impl_self->get_kind () == TyTy::TypeKind::POINTER;
+	  bool impl_self_is_ref = impl_self->get_kind () == TyTy::TypeKind::REF;
+	  if (receiver_is_raw_ptr && impl_self_is_ptr)
+	    {
+	      const TyTy::PointerType &sptr
+		= *static_cast<const TyTy::PointerType *> (impl_self);
+	      const TyTy::PointerType &ptr
+		= *static_cast<const TyTy::PointerType *> (raw);
+
+	      // we could do this via lang-item assemblies if we refactor this
+	      bool mut_match = sptr.mutability () == ptr.mutability ();
+	      if (!mut_match)
+		continue;
+	    }
+	  else if (receiver_is_ref && impl_self_is_ref)
+	    {
+	      const TyTy::ReferenceType &sptr
+		= *static_cast<const TyTy::ReferenceType *> (impl_self);
+	      const TyTy::ReferenceType &ptr
+		= *static_cast<const TyTy::ReferenceType *> (raw);
+
+	      // we could do this via lang-item assemblies if we refactor this
+	      bool mut_match = sptr.mutability () == ptr.mutability ();
+	      if (!mut_match)
+		continue;
+	    }
 
-    // see:
-    // https://gcc-rust.zulipchat.com/#narrow/stream/266897-general/topic/Method.20Resolution/near/338646280
-    // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/method/probe.rs#L650-L660
-    bool impl_self_is_ptr = impl_self->get_kind () == TyTy::TypeKind::POINTER;
-    bool impl_self_is_ref = impl_self->get_kind () == TyTy::TypeKind::REF;
-    if (receiver_is_raw_ptr && impl_self_is_ptr)
-      {
-	const TyTy::PointerType &sptr
-	  = *static_cast<const TyTy::PointerType *> (impl_self);
-	const TyTy::PointerType &ptr
-	  = *static_cast<const TyTy::PointerType *> (raw);
-
-	// we could do this via lang-item assemblies if we refactor this
-	bool mut_match = sptr.mutability () == ptr.mutability ();
-	if (!mut_match)
-	  return true;
-      }
-    else if (receiver_is_ref && impl_self_is_ref)
-      {
-	const TyTy::ReferenceType &sptr
-	  = *static_cast<const TyTy::ReferenceType *> (impl_self);
-	const TyTy::ReferenceType &ptr
-	  = *static_cast<const TyTy::ReferenceType *> (raw);
-
-	// we could do this via lang-item assemblies if we refactor this
-	bool mut_match = sptr.mutability () == ptr.mutability ();
-	if (!mut_match)
-	  return true;
-      }
+	  TyTy::BaseType *ty = nullptr;
+	  if (!query_type (func->get_mappings ().get_hirid (), &ty))
+	    continue;
+	  if (ty == nullptr || ty->get_kind () == TyTy::TypeKind::ERROR)
+	    continue;
+	  if (ty->get_kind () != TyTy::TypeKind::FNDEF)
+	    continue;
 
-    TyTy::BaseType *ty = nullptr;
-    if (!query_type (func->get_mappings ().get_hirid (), &ty))
-      return true;
-    if (ty == nullptr || ty->get_kind () == TyTy::TypeKind::ERROR)
-      return true;
-    if (ty->get_kind () != TyTy::TypeKind::FNDEF)
+	  TyTy::FnType *fnty = static_cast<TyTy::FnType *> (ty);
+	  inherent_impl_fns.emplace_back (func, impl, fnty);
+	}
       return true;
-
-    TyTy::FnType *fnty = static_cast<TyTy::FnType *> (ty);
-
-    inherent_impl_fns.emplace_back (func, impl, fnty);
-
-    return true;
-  });
+    });
 
   return inherent_impl_fns;
 }
@@ -332,7 +333,7 @@ MethodResolver::assemble_trait_impl_candidates (
   };
 
   if (specified_trait == nullptr)
-    mappings.iterate_impl_blocks (process_impl);
+    mappings.iterate_trait_impl_blocks (process_impl);
   else
     mappings.iterate_trait_impl_blocks (
       specified_trait->get_mappings ().get_nodeid (), process_impl);
@@ -484,15 +485,17 @@ MethodResolver::select (TyTy::BaseType &receiver)
   // Assemble candidates
   std::vector<impl_item_candidate> inherent_impl_fns;
   if (specified_trait == nullptr)
-    inherent_impl_fns = assemble_inherent_impl_candidates (receiver);
+    {
+      inherent_impl_fns = assemble_inherent_impl_candidates (receiver);
+      if (try_select_inherent_impl_candidates (receiver, inherent_impl_fns,
+					       false))
+	return true;
+    }
+
   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);
 
-  // Combine inherent and trait impl functions
-  inherent_impl_fns.insert (inherent_impl_fns.end (), trait_impl_fns.begin (),
-			    trait_impl_fns.end ());
-
   // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/method/probe.rs#L580-L694
 
   rust_debug ("inherent_impl_fns found {%lu}, trait_fns found {%lu}, "
@@ -503,15 +506,11 @@ MethodResolver::select (TyTy::BaseType &receiver)
 
   // Try selection in the priority order defined by Rust's method resolution:
 
-  // 1. Try inherent impl functions (non-trait impl blocks)
-  if (try_select_inherent_impl_candidates (receiver, inherent_impl_fns, false))
-    return true;
-
-  // 2. Try inherent impl functions from trait impl blocks
-  if (try_select_inherent_impl_candidates (receiver, inherent_impl_fns, true))
+  // 1. Try inherent impl functions from trait impl blocks
+  if (try_select_inherent_impl_candidates (receiver, trait_impl_fns, true))
     return true;
 
-  // 3. Try trait functions (lowest priority)
+  // 2. Try trait functions (lowest priority)
   return try_select_trait_impl_candidates (receiver, trait_fns);
 }
 
diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc
index 3d8da522e..74496c00d 100644
--- a/gcc/rust/util/rust-hir-map.cc
+++ b/gcc/rust/util/rust-hir-map.cc
@@ -472,6 +472,10 @@ Mappings::insert_hir_impl_block (HIR::ImplBlock *item)
 
   HirId impl_type_id = item->get_type ().get_mappings ().get_hirid ();
   hirImplBlockMappings[id] = item;
+  if (item->has_trait_ref ())
+    hirTraitImplBlockMappings[id] = item;
+  else
+    hirInherentImplBlockMappings[id] = item;
   hirImplBlockTypeMappings[impl_type_id] = item;
   insert_node_to_hir (item->get_mappings ().get_nodeid (), id);
 }
diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h
index 7595c49d6..b30c412fa 100644
--- a/gcc/rust/util/rust-hir-map.h
+++ b/gcc/rust/util/rust-hir-map.h
@@ -224,6 +224,22 @@ public:
   iterate_trait_impl_blocks (NodeId trait_node_id,
 			     std::function<bool (HirId, HIR::ImplBlock *)> cb);
 
+  template <typename Callback> void iterate_trait_impl_blocks (Callback &&cb)
+  {
+    for (auto it = hirTraitImplBlockMappings.begin ();
+	 it != hirTraitImplBlockMappings.end (); ++it)
+      if (!cb (it->first, it->second))
+	return;
+  }
+
+  template <typename Callback> void iterate_inherent_impl_blocks (Callback &&cb)
+  {
+    for (auto it = hirInherentImplBlockMappings.begin ();
+	 it != hirInherentImplBlockMappings.end (); ++it)
+      if (!cb (it->first, it->second))
+	return;
+  }
+
   void iterate_impl_blocks (std::function<bool (HirId, HIR::ImplBlock *)> cb);
 
   void iterate_trait_items (
@@ -411,6 +427,8 @@ private:
   std::map<HirId, HIR::SelfParam *> hirSelfParamMappings;
   std::map<HirId, HIR::ImplBlock *> hirImplItemsToImplMappings;
   std::map<HirId, HIR::ImplBlock *> hirImplBlockMappings;
+  std::map<HirId, HIR::ImplBlock *> hirInherentImplBlockMappings;
+  std::map<HirId, HIR::ImplBlock *> hirTraitImplBlockMappings;
   std::map<HirId, HIR::ImplBlock *> hirImplBlockTypeMappings;
   std::map<NodeId, std::vector<HIR::ImplBlock *>> hirAdtImplMappings;
   std::set<HIR::ImplBlock *> hirIndexedAdtImpls;
-- 
2.55.0



More information about the Gcc-rust mailing list