Skip to content

Commit

Permalink
Account for arbitrary self types in E0599
Browse files Browse the repository at this point in the history
  • Loading branch information
estebank committed Feb 21, 2020
1 parent 7818a1d commit 3a58953
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 17 deletions.
51 changes: 51 additions & 0 deletions src/librustc_typeck/check/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand All @@ -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.
Expand Down
6 changes: 2 additions & 4 deletions src/test/ui/issues/issue-5153.stderr
Original file line number Diff line number Diff line change
@@ -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

Expand Down
12 changes: 4 additions & 8 deletions src/test/ui/object-pointer-types.stderr
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down

0 comments on commit 3a58953

Please sign in to comment.