https://gcc.gnu.org/g:d005e9e6ec4eae673431b4346632dca77f439e86
commit r17-4331-gd005e9e6ec4eae673431b4346632dca77f439e86 Author: Philip Herron <[email protected]> Date: Thu Sep 3 21:29:30 2026 +0100 gccrs: Improve method resolution to use seperate indexes for impl's 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 <[email protected]> Diff: --- 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 e42c4b90a2e6..a2ecb26498a1 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 3d8da522eb18..74496c00d144 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 7595c49d6b09..b30c412fa681 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;
