From 7e4ca97cac069886c2e54674f973f723e68ee912 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Sat, 10 Apr 2021 17:40:32 +0100 Subject: 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. --- gcc/rust/typecheck/rust-hir-method-resolve.h | 79 +++++++-------------------- gcc/rust/typecheck/rust-hir-type-check-expr.h | 37 +++++++------ gcc/testsuite/rust.test/compile/generics15.rs | 21 +++++++ gcc/testsuite/rust.test/compile/generics16.rs | 29 ++++++++++ 4 files changed, 89 insertions(+), 77 deletions(-) create mode 100644 gcc/testsuite/rust.test/compile/generics15.rs create mode 100644 gcc/testsuite/rust.test/compile/generics16.rs (limited to 'gcc') 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 Probe (TyTy::BaseType *receiver, - HIR::PathExprSegment method_name) + static std::vector + Probe (std::vector &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 probed; + bool is_method_flag; + std::vector 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, bool); + +impl Foo { + fn bar(self) -> i32 { + self.0 + } +} + +impl Foo { + 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, bool); + +impl Foo { + fn new() -> Self { + Foo(123, true) + } + + fn bar(self) -> i32 { + self.0 + } +} + +impl Foo { + fn new() -> Self { + Foo(123f32, true) + } + + fn bar(self) -> f32 { + self.0 + } +} + +fn main() { + let a = Foo::::new(); + let aa: i32 = a.bar(); + + let b = Foo::::new(); + let bb: f32 = b.bar(); +} -- cgit v1.1