https://gcc.gnu.org/g:dc6454fa5506e7315e6d863857291ad74ae50103
commit r17-4293-gdc6454fa5506e7315e6d863857291ad74ae50103 Author: Philip Herron <[email protected]> Date: Sun Aug 23 20:18:02 2026 +0100 gccrs: Add method resolution probe support to take a trait to filter 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 <[email protected]> Diff: --- gcc/rust/typecheck/rust-hir-dot-operator.cc | 34 +++++++++++++++++++------- gcc/rust/typecheck/rust-hir-dot-operator.h | 7 ++++-- gcc/rust/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 d1095d553630..f74005e1ed83 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 31160ed9082a..79c5db1c079f 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 8ba1df7d260d..1c24c7c936bb 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 d7d0cc87c2a1..fc6a643077ef 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 2f7431a00c88..bfe04f0bc7a5 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 (
