diff options
| author | Esteban Küber <esteban@kuber.com.ar> | 2020-02-19 15:57:21 -0800 |
|---|---|---|
| committer | Esteban Küber <esteban@kuber.com.ar> | 2020-02-28 11:37:59 -0800 |
| commit | 01286408c1d4ac9d862801ac102ce4de44fc095b (patch) | |
| tree | a8bda7752acd9a00d3df68817a214c8066def7b5 /src | |
| parent | 392d853589721ffef1f32181d6c3959f0284e4fb (diff) | |
| download | rust-01286408c1d4ac9d862801ac102ce4de44fc095b.tar.gz rust-01286408c1d4ac9d862801ac102ce4de44fc095b.zip | |
Account for arbitrary self types in E0599
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc_typeck/check/method/suggest.rs | 51 | ||||
| -rw-r--r-- | src/test/ui/issues/issue-5153.stderr | 6 | ||||
| -rw-r--r-- | src/test/ui/object-pointer-types.stderr | 12 | ||||
| -rw-r--r-- | src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr | 8 |
4 files changed, 60 insertions, 17 deletions
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 410b8883a29..cfd6356b0a1 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -16,6 +16,7 @@ use rustc_hir::intravisit; use rustc_hir::{ExprKind, Node, QPath}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::traits::Obligation; +use rustc_span::symbol::kw; use rustc_span::{source_map, FileName, Span}; use syntax::ast; use syntax::util::lev_distance; @@ -893,6 +894,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source); + let mut arbitrary_rcvr = vec![]; // There are no traits implemented, so lets suggest some traits to // implement, by finding ones that have the item name, and are // legal to implement. @@ -909,12 +911,61 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && self .associated_item(info.def_id, item_name, Namespace::ValueNS) .filter(|item| { + if let ty::AssocKind::Method = item.kind { + let id = self.tcx.hir().as_local_hir_id(item.def_id); + if let Some(hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Method(fn_sig, method), + .. + })) = id.map(|id| self.tcx.hir().get(id)) + { + let self_first_arg = match method { + hir::TraitMethod::Required([ident, ..]) => { + ident.name == kw::SelfLower + } + hir::TraitMethod::Provided(body_id) => { + match &self.tcx.hir().body(*body_id).params[..] { + [hir::Param { + pat: + hir::Pat { + kind: + hir::PatKind::Binding( + _, + _, + ident, + .., + ), + .. + }, + .. + }, ..] => ident.name == kw::SelfLower, + _ => false, + } + } + _ => false, + }; + + if !fn_sig.decl.implicit_self.has_implicit_self() + && self_first_arg + { + if let Some(ty) = fn_sig.decl.inputs.get(0) { + arbitrary_rcvr.push(ty.span); + } + return false; + } + } + } // We only want to suggest public or local traits (#45781). item.vis == ty::Visibility::Public || info.def_id.is_local() }) .is_some() }) .collect::<Vec<_>>(); + for span in &arbitrary_rcvr { + err.span_label( + *span, + "the method might not be found because of this arbitrary self type", + ); + } if !candidates.is_empty() { // Sort from most relevant to least relevant. diff --git a/src/test/ui/issues/issue-5153.stderr b/src/test/ui/issues/issue-5153.stderr index 44ef73550f8..93aaf4b9d82 100644 --- a/src/test/ui/issues/issue-5153.stderr +++ b/src/test/ui/issues/issue-5153.stderr @@ -1,13 +1,11 @@ error[E0599]: no method named `foo` found for reference `&dyn Foo` in the current scope --> $DIR/issue-5153.rs:10:27 | -LL | trait Foo { - | --------- `Foo` defines an item `foo`, perhaps you need to implement it +LL | fn foo(self: Box<Self>); + | --------- the method might not be found because of this arbitrary self type ... LL | (&5isize as &dyn Foo).foo(); | ^^^ method not found in `&dyn Foo` - | - = help: items from traits can only be used if the trait is implemented and in scope error: aborting due to previous error diff --git a/src/test/ui/object-pointer-types.stderr b/src/test/ui/object-pointer-types.stderr index 07b7da94097..021aa8670f7 100644 --- a/src/test/ui/object-pointer-types.stderr +++ b/src/test/ui/object-pointer-types.stderr @@ -1,24 +1,20 @@ error[E0599]: no method named `owned` found for reference `&dyn Foo` in the current scope --> $DIR/object-pointer-types.rs:11:7 | -LL | trait Foo { - | --------- `Foo` defines an item `owned`, perhaps you need to implement it +LL | fn owned(self: Box<Self>); + | --------- the method might not be found because of this arbitrary self type ... LL | x.owned(); | ^^^^^ method not found in `&dyn Foo` - | - = help: items from traits can only be used if the trait is implemented and in scope error[E0599]: no method named `owned` found for mutable reference `&mut dyn Foo` in the current scope --> $DIR/object-pointer-types.rs:17:7 | -LL | trait Foo { - | --------- `Foo` defines an item `owned`, perhaps you need to implement it +LL | fn owned(self: Box<Self>); + | --------- the method might not be found because of this arbitrary self type ... LL | x.owned(); | ^^^^^ method not found in `&mut dyn Foo` - | - = help: items from traits can only be used if the trait is implemented and in scope error[E0599]: no method named `managed` found for struct `std::boxed::Box<(dyn Foo + 'static)>` in the current scope --> $DIR/object-pointer-types.rs:23:7 diff --git a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr index 999bbcca6bc..37873031da3 100644 --- a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr +++ b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr @@ -2,16 +2,14 @@ error[E0599]: no method named `foo` found for struct `A` in the current scope --> $DIR/point-at-arbitrary-self-type-trait-method.rs:9:7 | LL | trait B { fn foo(self: Box<Self>); } - | ------- --- the method is available for `std::boxed::Box<A>` here - | | - | `B` defines an item `foo`, perhaps you need to implement it + | --- --------- the method might not be found because of this arbitrary self type + | | + | the method is available for `std::boxed::Box<A>` here LL | struct A; | --------- method `foo` not found for this ... LL | A.foo() | ^^^ method not found in `A` - | - = help: items from traits can only be used if the trait is implemented and in scope error: aborting due to previous error |
