From: Philip Herron <herron.phi...@googlemail.com> Refactor the dot operator implementation to improve code organization and maintainability while preserving existing functionality.
gcc/rust/ChangeLog: * typecheck/rust-hir-dot-operator.cc: Major refactoring and cleanup. * typecheck/rust-hir-dot-operator.h: Add new helper methods. --- gcc/rust/typecheck/rust-hir-dot-operator.cc | 183 ++++++++++---------- gcc/rust/typecheck/rust-hir-dot-operator.h | 35 ++++ 2 files changed, 127 insertions(+), 91 deletions(-) diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.cc b/gcc/rust/typecheck/rust-hir-dot-operator.cc index c1165e9e5b1..7b7944c508d 100644 --- a/gcc/rust/typecheck/rust-hir-dot-operator.cc +++ b/gcc/rust/typecheck/rust-hir-dot-operator.cc @@ -102,26 +102,16 @@ MethodResolver::try_hook (const TyTy::BaseType &r) } } -bool -MethodResolver::select (TyTy::BaseType &receiver) +std::vector<MethodResolver::impl_item_candidate> +MethodResolver::assemble_inherent_impl_candidates ( + const TyTy::BaseType &receiver) { - rust_debug ("MethodResolver::select reciever=[%s] path=[%s]", - receiver.debug_str ().c_str (), - segment_name.as_string ().c_str ()); - - struct impl_item_candidate - { - HIR::Function *item; - HIR::ImplBlock *impl_block; - TyTy::FnType *ty; - }; - + std::vector<impl_item_candidate> inherent_impl_fns; const TyTy::BaseType *raw = receiver.destructure (); 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 - std::vector<impl_item_candidate> inherent_impl_fns; + // 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 (); @@ -190,16 +180,19 @@ MethodResolver::select (TyTy::BaseType &receiver) return true; }); - struct trait_item_candidate - { - const HIR::TraitItemFunc *item; - const HIR::Trait *trait; - TyTy::FnType *ty; - const TraitReference *reference; - const TraitItemReference *item_ref; - }; + return inherent_impl_fns; +} + +void +MethodResolver::assemble_trait_impl_candidates ( + const TyTy::BaseType &receiver, + std::vector<impl_item_candidate> &impl_candidates, + std::vector<trait_item_candidate> &trait_candidates) +{ + const TyTy::BaseType *raw = receiver.destructure (); + bool receiver_is_raw_ptr = raw->get_kind () == TyTy::TypeKind::POINTER; + bool receiver_is_ref = raw->get_kind () == TyTy::TypeKind::REF; - std::vector<trait_item_candidate> trait_fns; mappings.iterate_impl_blocks ([&] (HirId id, HIR::ImplBlock *impl) mutable -> bool { bool is_trait_impl = impl->has_trait_ref (); @@ -266,7 +259,7 @@ MethodResolver::select (TyTy::BaseType &receiver) continue; } - inherent_impl_fns.push_back ({func, impl, fnty}); + impl_candidates.push_back ({func, impl, fnty}); return true; } @@ -293,26 +286,15 @@ MethodResolver::select (TyTy::BaseType &receiver) TyTy::FnType *fnty = static_cast<TyTy::FnType *> (ty); trait_item_candidate candidate{func, trait, fnty, trait_ref, item_ref}; - trait_fns.push_back (candidate); + trait_candidates.push_back (candidate); return true; }); +} - // lookup specified bounds for an associated item - struct precdicate_candidate - { - TyTy::TypeBoundPredicateItem lookup; - TyTy::FnType *fntype; - }; - - // 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}, " - "predicate_items found {%lu}", - (unsigned long) inherent_impl_fns.size (), - (unsigned long) trait_fns.size (), - (unsigned long) predicate_items.size ()); - +bool +MethodResolver::try_select_predicate_candidates (TyTy::BaseType &receiver) +{ bool found_possible_candidate = false; for (const auto &predicate : predicate_items) { @@ -346,60 +328,33 @@ MethodResolver::select (TyTy::BaseType &receiver) found_possible_candidate = true; } } - if (found_possible_candidate) - { - return true; - } + return found_possible_candidate; +} - for (auto &impl_item : inherent_impl_fns) +bool +MethodResolver::try_select_inherent_impl_candidates ( + TyTy::BaseType &receiver, const std::vector<impl_item_candidate> &candidates, + bool trait_impl_blocks_only) +{ + bool found_possible_candidate = false; + for (auto &impl_item : candidates) { bool is_trait_impl_block = impl_item.impl_block->has_trait_ref (); - if (is_trait_impl_block) + if (trait_impl_blocks_only && !is_trait_impl_block) continue; - - TyTy::FnType *fn = impl_item.ty; - rust_assert (fn->is_method ()); - - TyTy::BaseType *fn_self = fn->get_self_type (); - rust_debug ("dot-operator impl_item fn_self={%s} can_eq receiver={%s}", - fn_self->debug_str ().c_str (), - receiver.debug_str ().c_str ()); - - auto res - = TypeCoercionRules::TryCoerce (&receiver, fn_self, UNDEF_LOCATION, - false /*allow-autoderef*/); - bool ok = !res.is_error (); - if (ok) - { - std::vector<Adjustment> adjs = append_adjustments (res.adjustments); - PathProbeCandidate::ImplItemCandidate c{impl_item.item, - impl_item.impl_block}; - auto try_result = MethodCandidate{ - PathProbeCandidate (PathProbeCandidate::CandidateType::IMPL_FUNC, - fn, impl_item.item->get_locus (), c), - adjs}; - result.insert (std::move (try_result)); - found_possible_candidate = true; - } - } - if (found_possible_candidate) - { - return true; - } - - for (auto &impl_item : inherent_impl_fns) - { - bool is_trait_impl_block = impl_item.impl_block->has_trait_ref (); - if (!is_trait_impl_block) + if (!trait_impl_blocks_only && is_trait_impl_block) continue; TyTy::FnType *fn = impl_item.ty; rust_assert (fn->is_method ()); TyTy::BaseType *fn_self = fn->get_self_type (); - rust_debug ( - "dot-operator trait_impl_item fn_self={%s} can_eq receiver={%s}", - fn_self->debug_str ().c_str (), receiver.debug_str ().c_str ()); + + const char *debug_prefix + = trait_impl_blocks_only ? "trait_impl_item" : "impl_item"; + rust_debug ("dot-operator %s fn_self={%s} can_eq receiver={%s}", + debug_prefix, fn_self->debug_str ().c_str (), + receiver.debug_str ().c_str ()); auto res = TypeCoercionRules::TryCoerce (&receiver, fn_self, UNDEF_LOCATION, @@ -418,12 +373,15 @@ MethodResolver::select (TyTy::BaseType &receiver) found_possible_candidate = true; } } - if (found_possible_candidate) - { - return true; - } + return found_possible_candidate; +} - for (auto trait_item : trait_fns) +bool +MethodResolver::try_select_trait_impl_candidates ( + TyTy::BaseType &receiver, const std::vector<trait_item_candidate> &candidates) +{ + bool found_possible_candidate = false; + for (auto trait_item : candidates) { TyTy::FnType *fn = trait_item.ty; rust_assert (fn->is_method ()); @@ -451,10 +409,53 @@ MethodResolver::select (TyTy::BaseType &receiver) found_possible_candidate = true; } } - return found_possible_candidate; } +bool +MethodResolver::select (TyTy::BaseType &receiver) +{ + rust_debug ("MethodResolver::select reciever=[%s] path=[%s]", + receiver.debug_str ().c_str (), + segment_name.as_string ().c_str ()); + + // Assemble candidates + std::vector<impl_item_candidate> 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); + + // 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}, " + "predicate_items found {%lu}", + (unsigned long) inherent_impl_fns.size (), + (unsigned long) trait_fns.size (), + (unsigned long) predicate_items.size ()); + + // Try selection in the priority order defined by Rust's method resolution: + + // 1. Try predicate candidates first (highest priority) + if (try_select_predicate_candidates (receiver)) + return true; + + // 2. Try inherent impl functions (non-trait impl blocks) + if (try_select_inherent_impl_candidates (receiver, inherent_impl_fns, false)) + return true; + + // 3. Try inherent impl functions from trait impl blocks + if (try_select_inherent_impl_candidates (receiver, inherent_impl_fns, true)) + return true; + + // 4. Try trait functions (lowest priority) + return try_select_trait_impl_candidates (receiver, trait_fns); +} + std::vector<MethodResolver::predicate_candidate> MethodResolver::get_predicate_items ( const HIR::PathIdentSegment &segment_name, const TyTy::BaseType &receiver, diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.h b/gcc/rust/typecheck/rust-hir-dot-operator.h index ab95a5a40c4..cc40472e0fa 100644 --- a/gcc/rust/typecheck/rust-hir-dot-operator.h +++ b/gcc/rust/typecheck/rust-hir-dot-operator.h @@ -65,6 +65,22 @@ public: const HIR::PathIdentSegment &segment_name, const TyTy::BaseType &receiver, const std::vector<TyTy::TypeBoundPredicate> &specified_bounds); + struct impl_item_candidate + { + HIR::Function *item; + HIR::ImplBlock *impl_block; + TyTy::FnType *ty; + }; + + struct trait_item_candidate + { + const HIR::TraitItemFunc *item; + const HIR::Trait *trait; + TyTy::FnType *ty; + const TraitReference *reference; + const TraitItemReference *item_ref; + }; + protected: MethodResolver (bool autoderef_flag, const HIR::PathIdentSegment &segment_name); @@ -77,6 +93,25 @@ private: std::vector<Adjustment> append_adjustments (const std::vector<Adjustment> &adjustments) const; + std::vector<impl_item_candidate> + assemble_inherent_impl_candidates (const TyTy::BaseType &receiver); + + void assemble_trait_impl_candidates ( + const TyTy::BaseType &receiver, + std::vector<impl_item_candidate> &impl_candidates, + std::vector<trait_item_candidate> &trait_candidates); + + bool try_select_predicate_candidates (TyTy::BaseType &receiver); + + bool try_select_inherent_impl_candidates ( + TyTy::BaseType &receiver, + const std::vector<impl_item_candidate> &candidates, + bool trait_impl_blocks_only); + + bool try_select_trait_impl_candidates ( + TyTy::BaseType &receiver, + const std::vector<trait_item_candidate> &candidates); + private: // search const HIR::PathIdentSegment &segment_name; -- 2.49.0