aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2021-04-10 17:40:32 +0100
committerPhilip Herron <philip.herron@embecosm.com>2021-04-12 22:39:45 +0100
commit7e4ca97cac069886c2e54674f973f723e68ee912 (patch)
tree8c40840d2527f2587b4cae90e8f7651cb6917188 /gcc/rust
parent85f587410612c8d2ec65dd23063a849d13005957 (diff)
downloadgcc-7e4ca97cac069886c2e54674f973f723e68ee912.zip
gcc-7e4ca97cac069886c2e54674f973f723e68ee912.tar.gz
gcc-7e4ca97cac069886c2e54674f973f723e68ee912.tar.bz2
Refactor Method resolution to take advantage of PathProbe
This canonicalizes method resolution to the Path Probe used for Path expr resolution. So any errors will gain the same diagnostics.
Diffstat (limited to 'gcc/rust')
-rw-r--r--gcc/rust/typecheck/rust-hir-method-resolve.h79
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h37
2 files changed, 39 insertions, 77 deletions
diff --git a/gcc/rust/typecheck/rust-hir-method-resolve.h b/gcc/rust/typecheck/rust-hir-method-resolve.h
index 35a5502..b2391e3 100644
--- a/gcc/rust/typecheck/rust-hir-method-resolve.h
+++ b/gcc/rust/typecheck/rust-hir-method-resolve.h
@@ -22,6 +22,7 @@
#include "rust-hir-type-check-base.h"
#include "rust-hir-full.h"
#include "rust-tyty.h"
+#include "rust-hir-path-probe.h"
#include "rust-substitution-mapper.h"
namespace Rust {
@@ -32,74 +33,32 @@ class MethodResolution : public TypeCheckBase
using Rust::Resolver::TypeCheckBase::visit;
public:
- static std::vector<HIR::Method *> Probe (TyTy::BaseType *receiver,
- HIR::PathExprSegment method_name)
+ static std::vector<PathProbeCandidate>
+ Probe (std::vector<PathProbeCandidate> &path_candidates)
{
- MethodResolution probe (receiver, method_name);
-
- // lookup impl items for this crate and find all methods that can resolve to
- // this receiver
- probe.mappings->iterate_impl_items (
- [&] (HirId id, HIR::InherentImplItem *item,
- HIR::InherentImpl *impl) mutable -> bool {
- item->accept_vis (probe);
- return true;
- });
-
- return probe.probed;
+ MethodResolution probe;
+ for (auto &c : path_candidates)
+ probe.process_candidate (c);
+
+ return probe.candidates;
}
- void visit (HIR::Method &method) override
+ void process_candidate (PathProbeCandidate &candidate)
{
- TyTy::BaseType *self_lookup = nullptr;
- if (!context->lookup_type (
- method.get_self_param ().get_mappings ().get_hirid (), &self_lookup))
- {
- rust_error_at (method.get_self_param ().get_locus (),
- "failed to lookup lookup self type in MethodProbe");
- return;
- }
-
- // are the names the same
- HIR::PathIdentSegment seg = method_name.get_segment ();
- if (seg.as_string ().compare (method.get_method_name ()) != 0)
- {
- // if the method name does not match then this is not a valid match
- return;
- }
-
- if (self_lookup->get_kind () != receiver->get_kind ())
- return;
-
- if (receiver->has_subsititions_defined ()
- != self_lookup->has_subsititions_defined ())
- return;
-
- if (self_lookup->has_subsititions_defined ())
- {
- // we assume the receiver should be fully substituted at this stage
- self_lookup = SubstMapperFromExisting::Resolve (receiver, self_lookup);
- }
-
- if (!receiver->is_equal (*self_lookup))
- {
- // incompatible self argument then this is not a valid method for this
- // receiver
- return;
- }
-
- probed.push_back (&method);
+ is_method_flag = false;
+ candidate.impl_item->accept_vis (*this);
+
+ if (is_method_flag)
+ candidates.push_back (candidate);
}
-private:
- MethodResolution (TyTy::BaseType *receiver, HIR::PathExprSegment method_name)
- : TypeCheckBase (), receiver (receiver), method_name (method_name)
- {}
+ void visit (HIR::Method &method) override { is_method_flag = true; }
- TyTy::BaseType *receiver;
- HIR::PathExprSegment method_name;
+private:
+ MethodResolution () : TypeCheckBase () {}
- std::vector<HIR::Method *> probed;
+ bool is_method_flag;
+ std::vector<PathProbeCandidate> candidates;
};
} // namespace Resolver
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index b946812..cb2f250 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -210,34 +210,37 @@ public:
// which is simple. There will need to be adjustments to ensure we can turn
// the receiver into borrowed references etc
- auto probes
- = MethodResolution::Probe (receiver_tyty, expr.get_method_name ());
- if (probes.size () == 0)
+ auto candidates
+ = PathProbeType::Probe (receiver_tyty,
+ expr.get_method_name ().get_segment ());
+ if (candidates.size () == 0)
{
rust_error_at (expr.get_locus (),
"failed to resolve the PathExprSegment to any Method");
return;
}
- else if (probes.size () > 1)
+
+ // filter all methods
+ auto possible_methods = MethodResolution::Probe (candidates);
+ if (possible_methods.size () == 0)
{
- rust_error_at (
- expr.get_locus (),
- "multiple candidates in MethodCallExpr have been probed is "
- "not currently supported");
+ rust_error_at (expr.get_method_name ().get_locus (),
+ "no method named %s found in scope",
+ expr.get_method_name ().as_string ().c_str ());
return;
}
-
- auto resolved_method = probes.at (0);
- TyTy::BaseType *lookup_tyty;
- if (!context->lookup_type (resolved_method->get_mappings ().get_hirid (),
- &lookup_tyty))
+ else if (possible_methods.size () > 1)
{
- rust_error_at (resolved_method->get_locus (),
- "failed to lookup type for CallExpr: %s",
- expr.as_string ().c_str ());
+ ReportMultipleCandidateError::Report (
+ possible_methods, expr.get_method_name ().get_segment (),
+ expr.get_method_name ().get_locus ());
return;
}
+ auto resolved_candidate = possible_methods.at (0);
+ HIR::InherentImplItem *resolved_method = resolved_candidate.impl_item;
+ TyTy::BaseType *lookup_tyty = resolved_candidate.ty;
+
TyTy::BaseType *lookup = lookup_tyty;
if (lookup_tyty->get_kind () == TyTy::TypeKind::FNDEF)
{
@@ -270,7 +273,7 @@ public:
// set up the resolved name on the path
resolver->insert_resolved_name (
expr.get_mappings ().get_nodeid (),
- resolved_method->get_mappings ().get_nodeid ());
+ resolved_method->get_impl_mappings ().get_nodeid ());
// return the result of the function back
infered = function_ret_tyty;