From: Philip Herron <[email protected]>
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]>
---
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