diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-05-10 20:19:29 +0100 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2021-05-10 20:19:29 +0100 |
commit | 338b20ed370b3b4a7ae601e234099eaaa7d056b3 (patch) | |
tree | d5c23bd1a05db839890655780aae6dfac44dd838 | |
parent | e0c5afe70d33d902cf89f2e0ced5431a50521dcd (diff) | |
download | gcc-338b20ed370b3b4a7ae601e234099eaaa7d056b3.zip gcc-338b20ed370b3b4a7ae601e234099eaaa7d056b3.tar.gz gcc-338b20ed370b3b4a7ae601e234099eaaa7d056b3.tar.bz2 |
Ensure method resolution resolves to an actual method
We need to check for rustc --explain E0599 so when we have a method call
that it must resolve to an actual method impl item.
-rw-r--r-- | gcc/rust/hir/tree/rust-hir-item.h | 6 | ||||
-rw-r--r-- | gcc/rust/hir/tree/rust-hir.h | 2 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-method-resolve.h | 67 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-expr.h | 53 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/xfail_compile/method1.rs | 14 |
5 files changed, 49 insertions, 93 deletions
diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index 648999b..fc67d60 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -745,6 +745,8 @@ public: Location get_locus () const { return locus; } + Location get_impl_locus () const final { return get_locus (); } + std::unique_ptr<BlockExpr> &get_function_body () { return function_body; } const std::unique_ptr<BlockExpr> &get_function_body () const { @@ -1366,6 +1368,8 @@ public: Location get_locus () const { return locus; } + Location get_impl_locus () const final { return get_locus (); } + void accept_vis (HIRVisitor &vis) override; Analysis::NodeMapping get_impl_mappings () const override @@ -2266,6 +2270,8 @@ public: Location get_locus () const { return locus; } + Location get_impl_locus () const final { return get_locus (); } + void accept_vis (HIRVisitor &vis) override; Type *get_type () { return type.get (); } diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h index 244ff3d..f6fa62d 100644 --- a/gcc/rust/hir/tree/rust-hir.h +++ b/gcc/rust/hir/tree/rust-hir.h @@ -1295,6 +1295,8 @@ public: virtual void accept_vis (HIRVisitor &vis) = 0; virtual Analysis::NodeMapping get_impl_mappings () const = 0; + + virtual Location get_impl_locus () const = 0; }; // Abstract base class for items used in a trait impl diff --git a/gcc/rust/typecheck/rust-hir-method-resolve.h b/gcc/rust/typecheck/rust-hir-method-resolve.h deleted file mode 100644 index b2391e3..0000000 --- a/gcc/rust/typecheck/rust-hir-method-resolve.h +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (C) 2020 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// <http://www.gnu.org/licenses/>. - -#ifndef RUST_HIR_METHOD_RESOLVE_H -#define RUST_HIR_METHOD_RESOLVE_H - -#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 { -namespace Resolver { - -class MethodResolution : public TypeCheckBase -{ - using Rust::Resolver::TypeCheckBase::visit; - -public: - static std::vector<PathProbeCandidate> - Probe (std::vector<PathProbeCandidate> &path_candidates) - { - MethodResolution probe; - for (auto &c : path_candidates) - probe.process_candidate (c); - - return probe.candidates; - } - - void process_candidate (PathProbeCandidate &candidate) - { - is_method_flag = false; - candidate.impl_item->accept_vis (*this); - - if (is_method_flag) - candidates.push_back (candidate); - } - - void visit (HIR::Method &method) override { is_method_flag = true; } - -private: - MethodResolution () : TypeCheckBase () {} - - bool is_method_flag; - std::vector<PathProbeCandidate> candidates; -}; - -} // namespace Resolver -} // namespace Rust - -#endif // RUST_HIR_METHOD_RESOLVE_H diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index d82e82b..5df6b70 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -24,7 +24,6 @@ #include "rust-tyty.h" #include "rust-tyty-call.h" #include "rust-hir-type-check-struct-field.h" -#include "rust-hir-method-resolve.h" #include "rust-hir-path-probe.h" #include "rust-substitution-mapper.h" #include "rust-hir-const-fold.h" @@ -221,43 +220,45 @@ public: "failed to resolve the PathExprSegment to any Method"); return; } - - // filter all methods - auto possible_methods = MethodResolution::Probe (candidates); - if (possible_methods.size () == 0) - { - 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; - } - else if (possible_methods.size () > 1) + else if (candidates.size () > 1) { ReportMultipleCandidateError::Report ( - possible_methods, expr.get_method_name ().get_segment (), + candidates, expr.get_method_name ().get_segment (), expr.get_method_name ().get_locus ()); return; } - auto resolved_candidate = possible_methods.at (0); + auto resolved_candidate = candidates.at (0); HIR::InherentImplItem *resolved_method = resolved_candidate.impl_item; TyTy::BaseType *lookup_tyty = resolved_candidate.ty; + if (lookup_tyty->get_kind () != TyTy::TypeKind::FNDEF) + { + RichLocation r (expr.get_method_name ().get_locus ()); + r.add_range (resolved_method->get_impl_locus ()); + rust_error_at (r, "associated impl item is not a method"); + return; + } + TyTy::BaseType *lookup = lookup_tyty; - if (lookup_tyty->get_kind () == TyTy::TypeKind::FNDEF) + TyTy::FnType *fn = static_cast<TyTy::FnType *> (lookup); + if (!fn->is_method ()) { - TyTy::FnType *fn = static_cast<TyTy::FnType *> (lookup); - if (receiver_tyty->get_kind () == TyTy::TypeKind::ADT) + RichLocation r (expr.get_method_name ().get_locus ()); + r.add_range (resolved_method->get_impl_locus ()); + rust_error_at (r, "associated function is not a method"); + return; + } + + if (receiver_tyty->get_kind () == TyTy::TypeKind::ADT) + { + TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (receiver_tyty); + if (adt->has_substitutions () && fn->needs_substitution ()) { - TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (receiver_tyty); - if (adt->has_substitutions () && fn->needs_substitution ()) - { - rust_assert (adt->was_substituted ()); - auto used_args_in_prev_segment = GetUsedSubstArgs::From (adt); - lookup - = SubstMapperInternal::Resolve (fn, - used_args_in_prev_segment); - } + rust_assert (adt->was_substituted ()); + auto used_args_in_prev_segment = GetUsedSubstArgs::From (adt); + lookup + = SubstMapperInternal::Resolve (fn, used_args_in_prev_segment); } } diff --git a/gcc/testsuite/rust.test/xfail_compile/method1.rs b/gcc/testsuite/rust.test/xfail_compile/method1.rs new file mode 100644 index 0000000..51bc821 --- /dev/null +++ b/gcc/testsuite/rust.test/xfail_compile/method1.rs @@ -0,0 +1,14 @@ +// { dg-excess-errors "Noisy error and debug" } +struct Foo(i32); + +impl Foo { + fn test() {} +} + +pub fn main() { + let a; + a = Foo(123); + + a.test() + // { dg-error "associated function is not a method" "" { target *-*-* } .-1 } +} |