public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/rust/master] Refactor the autoderef cycle to be a reuseable base class
@ 2022-08-06 12:09 Thomas Schwinge
0 siblings, 0 replies; only message in thread
From: Thomas Schwinge @ 2022-08-06 12:09 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:ffb419d6a46302126944066ef46bd0c9f590ee30
commit ffb419d6a46302126944066ef46bd0c9f590ee30
Author: Philip Herron <philip.herron@embecosm.com>
Date: Fri Jul 29 14:29:51 2022 +0100
Refactor the autoderef cycle to be a reuseable base class
The autoderef cycle is used to coerce/select apropriate methods during
method resolution. This same cycle of autoderef is also used as coercion
sites. In order to avoid duplicating the logic this extracts out a useful
base class that can be implemented to support this elsewhere.
Diff:
---
gcc/rust/typecheck/rust-autoderef.cc | 124 +++++++++++++++++++
gcc/rust/typecheck/rust-autoderef.h | 21 ++++
gcc/rust/typecheck/rust-hir-dot-operator.cc | 177 +++++-----------------------
gcc/rust/typecheck/rust-hir-dot-operator.h | 41 ++++---
4 files changed, 197 insertions(+), 166 deletions(-)
diff --git a/gcc/rust/typecheck/rust-autoderef.cc b/gcc/rust/typecheck/rust-autoderef.cc
index 986ff460490..0025e7ef80d 100644
--- a/gcc/rust/typecheck/rust-autoderef.cc
+++ b/gcc/rust/typecheck/rust-autoderef.cc
@@ -268,5 +268,129 @@ resolve_operator_overload_fn (
return true;
}
+AutoderefCycle::AutoderefCycle (bool autoderef_flag)
+ : autoderef_flag (autoderef_flag)
+{}
+
+AutoderefCycle::~AutoderefCycle () {}
+
+void
+AutoderefCycle::try_hook (const TyTy::BaseType &)
+{}
+
+bool
+AutoderefCycle::cycle (const TyTy::BaseType *receiver)
+{
+ const TyTy::BaseType *r = receiver;
+ while (true)
+ {
+ if (try_autoderefed (r))
+ return true;
+
+ // 4. deref to to 1, if cannot deref then quit
+ if (autoderef_flag)
+ return false;
+
+ // try unsize
+ Adjustment unsize = Adjuster::try_unsize_type (r);
+ if (!unsize.is_error ())
+ {
+ adjustments.push_back (unsize);
+ auto unsize_r = unsize.get_expected ();
+
+ if (try_autoderefed (unsize_r))
+ return true;
+
+ adjustments.pop_back ();
+ }
+
+ Adjustment deref
+ = Adjuster::try_deref_type (r, Analysis::RustLangItem::ItemType::DEREF);
+ if (!deref.is_error ())
+ {
+ auto deref_r = deref.get_expected ();
+ adjustments.push_back (deref);
+
+ if (try_autoderefed (deref_r))
+ return true;
+
+ adjustments.pop_back ();
+ }
+
+ Adjustment deref_mut = Adjuster::try_deref_type (
+ r, Analysis::RustLangItem::ItemType::DEREF_MUT);
+ if (!deref_mut.is_error ())
+ {
+ auto deref_r = deref_mut.get_expected ();
+ adjustments.push_back (deref_mut);
+
+ if (try_autoderefed (deref_r))
+ return true;
+
+ adjustments.pop_back ();
+ }
+
+ if (!deref_mut.is_error ())
+ {
+ auto deref_r = deref_mut.get_expected ();
+ adjustments.push_back (deref_mut);
+ Adjustment raw_deref = Adjuster::try_raw_deref_type (deref_r);
+ adjustments.push_back (raw_deref);
+ deref_r = raw_deref.get_expected ();
+
+ if (try_autoderefed (deref_r))
+ return true;
+
+ adjustments.pop_back ();
+ adjustments.pop_back ();
+ }
+
+ if (!deref.is_error ())
+ {
+ r = deref.get_expected ();
+ adjustments.push_back (deref);
+ }
+ Adjustment raw_deref = Adjuster::try_raw_deref_type (r);
+ if (raw_deref.is_error ())
+ return false;
+
+ r = raw_deref.get_expected ();
+ adjustments.push_back (raw_deref);
+ }
+ return false;
+}
+
+bool
+AutoderefCycle::try_autoderefed (const TyTy::BaseType *r)
+{
+ try_hook (*r);
+
+ // 1. try raw
+ if (select (*r))
+ return true;
+
+ // 2. try ref
+ TyTy::ReferenceType *r1
+ = new TyTy::ReferenceType (r->get_ref (), TyTy::TyVar (r->get_ref ()),
+ Mutability::Imm);
+ adjustments.push_back (Adjustment (Adjustment::AdjustmentType::IMM_REF, r1));
+ if (select (*r1))
+ return true;
+
+ adjustments.pop_back ();
+
+ // 3. try mut ref
+ TyTy::ReferenceType *r2
+ = new TyTy::ReferenceType (r->get_ref (), TyTy::TyVar (r->get_ref ()),
+ Mutability::Mut);
+ adjustments.push_back (Adjustment (Adjustment::AdjustmentType::MUT_REF, r2));
+ if (select (*r2))
+ return true;
+
+ adjustments.pop_back ();
+
+ return false;
+}
+
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-autoderef.h b/gcc/rust/typecheck/rust-autoderef.h
index 369744e3b8c..159f4c06cbc 100644
--- a/gcc/rust/typecheck/rust-autoderef.h
+++ b/gcc/rust/typecheck/rust-autoderef.h
@@ -144,6 +144,27 @@ private:
const TyTy::BaseType *base;
};
+class AutoderefCycle
+{
+protected:
+ AutoderefCycle (bool autoderef_flag);
+
+ virtual ~AutoderefCycle ();
+
+ virtual bool select (const TyTy::BaseType &autoderefed) = 0;
+
+ // optional: this is a chance to hook in to grab predicate items on the raw
+ // type
+ virtual void try_hook (const TyTy::BaseType &);
+
+ bool cycle (const TyTy::BaseType *receiver);
+
+ bool try_autoderefed (const TyTy::BaseType *r);
+
+ bool autoderef_flag;
+ std::vector<Adjustment> adjustments;
+};
+
} // namespace Resolver
} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.cc b/gcc/rust/typecheck/rust-hir-dot-operator.cc
index 104bd16080e..d45f0903478 100644
--- a/gcc/rust/typecheck/rust-hir-dot-operator.cc
+++ b/gcc/rust/typecheck/rust-hir-dot-operator.cc
@@ -23,151 +23,32 @@
namespace Rust {
namespace Resolver {
+MethodResolver::MethodResolver (bool autoderef_flag,
+ const HIR::PathIdentSegment &segment_name)
+ : AutoderefCycle (autoderef_flag), mappings (Analysis::Mappings::get ()),
+ context (TypeCheckContext::get ()), segment_name (segment_name),
+ try_result (MethodCandidate::get_error ())
+{}
+
MethodCandidate
MethodResolver::Probe (const TyTy::BaseType *receiver,
const HIR::PathIdentSegment &segment_name,
bool autoderef_flag)
{
- const TyTy::BaseType *r = receiver;
- std::vector<Adjustment> adjustments;
- while (true)
- {
- auto res = Try (r, segment_name, adjustments);
- if (!res.is_error ())
- return res;
-
- // 4. deref to to 1, if cannot deref then quit
- if (autoderef_flag)
- return MethodCandidate::get_error ();
-
- // try unsize
- Adjustment unsize = Adjuster::try_unsize_type (r);
- if (!unsize.is_error ())
- {
- adjustments.push_back (unsize);
- auto unsize_r = unsize.get_expected ();
- auto res = Try (unsize_r, segment_name, adjustments);
- if (!res.is_error ())
- {
- return res;
- }
-
- adjustments.pop_back ();
- }
-
- Adjustment deref
- = Adjuster::try_deref_type (r, Analysis::RustLangItem::ItemType::DEREF);
- if (!deref.is_error ())
- {
- auto deref_r = deref.get_expected ();
- adjustments.push_back (deref);
- auto res = Try (deref_r, segment_name, adjustments);
- if (!res.is_error ())
- {
- return res;
- }
-
- adjustments.pop_back ();
- }
-
- Adjustment deref_mut = Adjuster::try_deref_type (
- r, Analysis::RustLangItem::ItemType::DEREF_MUT);
- if (!deref_mut.is_error ())
- {
- auto deref_r = deref_mut.get_expected ();
- adjustments.push_back (deref_mut);
- auto res = Try (deref_r, segment_name, adjustments);
- if (!res.is_error ())
- {
- return res;
- }
-
- adjustments.pop_back ();
- }
-
- if (!deref_mut.is_error ())
- {
- auto deref_r = deref_mut.get_expected ();
- adjustments.push_back (deref_mut);
- Adjustment raw_deref = Adjuster::try_raw_deref_type (deref_r);
- adjustments.push_back (raw_deref);
- deref_r = raw_deref.get_expected ();
-
- auto res = Try (deref_r, segment_name, adjustments);
- if (!res.is_error ())
- {
- return res;
- }
-
- adjustments.pop_back ();
- adjustments.pop_back ();
- }
-
- if (!deref.is_error ())
- {
- r = deref.get_expected ();
- adjustments.push_back (deref);
- }
- Adjustment raw_deref = Adjuster::try_raw_deref_type (r);
- if (raw_deref.is_error ())
- return MethodCandidate::get_error ();
-
- r = raw_deref.get_expected ();
- adjustments.push_back (raw_deref);
- }
- return MethodCandidate::get_error ();
+ MethodResolver resolver (autoderef_flag, segment_name);
+ bool ok = resolver.cycle (receiver);
+ return ok ? resolver.try_result : MethodCandidate::get_error ();
}
-MethodCandidate
-MethodResolver::Try (const TyTy::BaseType *r,
- const HIR::PathIdentSegment &segment_name,
- std::vector<Adjustment> &adjustments)
+void
+MethodResolver::try_hook (const TyTy::BaseType &r)
{
- PathProbeCandidate c = PathProbeCandidate::get_error ();
- const std::vector<TyTy::TypeBoundPredicate> &specified_bounds
- = r->get_specified_bounds ();
- const std::vector<MethodResolver::predicate_candidate> predicate_items
- = get_predicate_items (segment_name, *r, specified_bounds);
-
- // 1. try raw
- MethodResolver raw (*r, segment_name, predicate_items);
- c = raw.select ();
- if (!c.is_error ())
- {
- return MethodCandidate{c, adjustments};
- }
-
- // 2. try ref
- TyTy::ReferenceType *r1
- = new TyTy::ReferenceType (r->get_ref (), TyTy::TyVar (r->get_ref ()),
- Mutability::Imm);
- MethodResolver imm_ref (*r1, segment_name, predicate_items);
- c = imm_ref.select ();
- if (!c.is_error ())
- {
- adjustments.push_back (
- Adjustment (Adjustment::AdjustmentType::IMM_REF, r1));
- return MethodCandidate{c, adjustments};
- }
-
- // 3. try mut ref
- TyTy::ReferenceType *r2
- = new TyTy::ReferenceType (r->get_ref (), TyTy::TyVar (r->get_ref ()),
- Mutability::Mut);
- MethodResolver mut_ref (*r2, segment_name, predicate_items);
- c = mut_ref.select ();
- if (!c.is_error ())
- {
- adjustments.push_back (
- Adjustment (Adjustment::AdjustmentType::MUT_REF, r2));
- return MethodCandidate{c, adjustments};
- }
-
- return MethodCandidate::get_error ();
+ const auto &specified_bounds = r.get_specified_bounds ();
+ predicate_items = get_predicate_items (segment_name, r, specified_bounds);
}
-PathProbeCandidate
-MethodResolver::select ()
+bool
+MethodResolver::select (const TyTy::BaseType &receiver)
{
struct impl_item_candidate
{
@@ -300,9 +181,11 @@ MethodResolver::select ()
{
PathProbeCandidate::ImplItemCandidate c{impl_item.item,
impl_item.impl_block};
- return PathProbeCandidate (
- PathProbeCandidate::CandidateType::IMPL_FUNC, fn,
- impl_item.item->get_locus (), c);
+ try_result = MethodCandidate{
+ PathProbeCandidate (PathProbeCandidate::CandidateType::IMPL_FUNC,
+ fn, impl_item.item->get_locus (), c),
+ adjustments};
+ return true;
}
}
@@ -317,9 +200,11 @@ MethodResolver::select ()
PathProbeCandidate::TraitItemCandidate c{trait_item.reference,
trait_item.item_ref,
nullptr};
- return PathProbeCandidate (
- PathProbeCandidate::CandidateType::TRAIT_FUNC, fn,
- trait_item.item->get_locus (), c);
+ try_result = MethodCandidate{
+ PathProbeCandidate (PathProbeCandidate::CandidateType::TRAIT_FUNC,
+ fn, trait_item.item->get_locus (), c),
+ adjustments};
+ return true;
}
}
@@ -338,13 +223,15 @@ MethodResolver::select ()
PathProbeCandidate::TraitItemCandidate c{trait_ref, trait_item,
nullptr};
- return PathProbeCandidate (
- PathProbeCandidate::CandidateType::TRAIT_FUNC, fn->clone (),
- trait_item->get_locus (), c);
+ try_result = MethodCandidate{
+ PathProbeCandidate (PathProbeCandidate::CandidateType::TRAIT_FUNC,
+ fn->clone (), trait_item->get_locus (), c),
+ adjustments};
+ return true;
}
}
- return PathProbeCandidate::get_error ();
+ return false;
}
std::vector<MethodResolver::predicate_candidate>
diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.h b/gcc/rust/typecheck/rust-hir-dot-operator.h
index ef1038bd78c..750601a2d9e 100644
--- a/gcc/rust/typecheck/rust-hir-dot-operator.h
+++ b/gcc/rust/typecheck/rust-hir-dot-operator.h
@@ -37,43 +37,42 @@ struct MethodCandidate
bool is_error () const { return candidate.is_error (); }
};
-class MethodResolver : public TypeCheckBase
+class MethodResolver : protected AutoderefCycle
{
-protected:
- using Rust::Resolver::TypeCheckBase::visit;
-
public:
- static MethodCandidate Probe (const TyTy::BaseType *receiver,
- const HIR::PathIdentSegment &segment_name,
- bool autoderef_flag = false);
-
-protected:
struct predicate_candidate
{
TyTy::TypeBoundPredicateItem lookup;
TyTy::FnType *fntype;
};
- static MethodCandidate Try (const TyTy::BaseType *r,
- const HIR::PathIdentSegment &segment_name,
- std::vector<Adjustment> &adjustments);
+ static MethodCandidate Probe (const TyTy::BaseType *receiver,
+ const HIR::PathIdentSegment &segment_name,
+ bool autoderef_flag = false);
static std::vector<predicate_candidate> get_predicate_items (
const HIR::PathIdentSegment &segment_name, const TyTy::BaseType &receiver,
const std::vector<TyTy::TypeBoundPredicate> &specified_bounds);
- PathProbeCandidate select ();
+protected:
+ MethodResolver (bool autoderef_flag,
+ const HIR::PathIdentSegment &segment_name);
- MethodResolver (
- const TyTy::BaseType &receiver, const HIR::PathIdentSegment &segment_name,
- const std::vector<MethodResolver::predicate_candidate> &predicate_items)
- : receiver (receiver), segment_name (segment_name),
- predicate_items (predicate_items)
- {}
+ void try_hook (const TyTy::BaseType &r) override;
- const TyTy::BaseType &receiver;
+ bool select (const TyTy::BaseType &receiver) override;
+
+private:
+ // context info
+ Analysis::Mappings *mappings;
+ TypeCheckContext *context;
+
+ // search
const HIR::PathIdentSegment &segment_name;
- const std::vector<MethodResolver::predicate_candidate> &predicate_items;
+ std::vector<MethodResolver::predicate_candidate> predicate_items;
+
+ // mutable fields
+ MethodCandidate try_result;
};
} // namespace Resolver
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2022-08-06 12:09 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-06 12:09 [gcc/devel/rust/master] Refactor the autoderef cycle to be a reuseable base class Thomas Schwinge
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).