diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-04-10 17:40:32 +0100 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2021-04-12 22:39:45 +0100 |
commit | 7e4ca97cac069886c2e54674f973f723e68ee912 (patch) | |
tree | 8c40840d2527f2587b4cae90e8f7651cb6917188 | |
parent | 85f587410612c8d2ec65dd23063a849d13005957 (diff) | |
download | gcc-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.h | 79 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-expr.h | 37 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/compile/generics15.rs | 21 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/compile/generics16.rs | 29 |
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(); +} |