aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2021-05-10 20:19:29 +0100
committerPhilip Herron <philip.herron@embecosm.com>2021-05-10 20:19:29 +0100
commit338b20ed370b3b4a7ae601e234099eaaa7d056b3 (patch)
treed5c23bd1a05db839890655780aae6dfac44dd838
parente0c5afe70d33d902cf89f2e0ced5431a50521dcd (diff)
downloadgcc-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.h6
-rw-r--r--gcc/rust/hir/tree/rust-hir.h2
-rw-r--r--gcc/rust/typecheck/rust-hir-method-resolve.h67
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h53
-rw-r--r--gcc/testsuite/rust.test/xfail_compile/method1.rs14
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 }
+}