aboutsummaryrefslogtreecommitdiff
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
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.
-rw-r--r--gcc/rust/typecheck/rust-hir-method-resolve.h79
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h37
-rw-r--r--gcc/testsuite/rust.test/compile/generics15.rs21
-rw-r--r--gcc/testsuite/rust.test/compile/generics16.rs29
4 files changed, 89 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;
diff --git a/gcc/testsuite/rust.test/compile/generics15.rs b/gcc/testsuite/rust.test/compile/generics15.rs
new file mode 100644
index 0000000..adf02ee
--- /dev/null
+++ b/gcc/testsuite/rust.test/compile/generics15.rs
@@ -0,0 +1,21 @@
+struct Foo<T>(T, bool);
+
+impl Foo<i32> {
+ fn bar(self) -> i32 {
+ self.0
+ }
+}
+
+impl Foo<f32> {
+ fn bar(self) -> f32 {
+ self.0
+ }
+}
+
+fn main() {
+ let a = Foo(123, true);
+ let aa = a.bar();
+
+ let b = Foo(456f32, true);
+ let bb = b.bar();
+}
diff --git a/gcc/testsuite/rust.test/compile/generics16.rs b/gcc/testsuite/rust.test/compile/generics16.rs
new file mode 100644
index 0000000..1af24e0
--- /dev/null
+++ b/gcc/testsuite/rust.test/compile/generics16.rs
@@ -0,0 +1,29 @@
+struct Foo<T>(T, bool);
+
+impl Foo<i32> {
+ fn new() -> Self {
+ Foo(123, true)
+ }
+
+ fn bar(self) -> i32 {
+ self.0
+ }
+}
+
+impl Foo<f32> {
+ fn new() -> Self {
+ Foo(123f32, true)
+ }
+
+ fn bar(self) -> f32 {
+ self.0
+ }
+}
+
+fn main() {
+ let a = Foo::<i32>::new();
+ let aa: i32 = a.bar();
+
+ let b = Foo::<f32>::new();
+ let bb: f32 = b.bar();
+}