Skip to content

Commit 3a58953

Browse files
committed
Account for arbitrary self types in E0599
1 parent 7818a1d commit 3a58953

File tree

4 files changed

+60
-17
lines changed

4 files changed

+60
-17
lines changed

src/librustc_typeck/check/method/suggest.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use rustc_hir::intravisit;
1616
use rustc_hir::{ExprKind, Node, QPath};
1717
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
1818
use rustc_infer::traits::Obligation;
19+
use rustc_span::symbol::kw;
1920
use rustc_span::{source_map, FileName, Span};
2021
use syntax::ast;
2122
use syntax::util::lev_distance;
@@ -893,6 +894,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
893894

894895
let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
895896

897+
let mut arbitrary_rcvr = vec![];
896898
// There are no traits implemented, so lets suggest some traits to
897899
// implement, by finding ones that have the item name, and are
898900
// legal to implement.
@@ -909,12 +911,61 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
909911
&& self
910912
.associated_item(info.def_id, item_name, Namespace::ValueNS)
911913
.filter(|item| {
914+
if let ty::AssocKind::Method = item.kind {
915+
let id = self.tcx.hir().as_local_hir_id(item.def_id);
916+
if let Some(hir::Node::TraitItem(hir::TraitItem {
917+
kind: hir::TraitItemKind::Method(fn_sig, method),
918+
..
919+
})) = id.map(|id| self.tcx.hir().get(id))
920+
{
921+
let self_first_arg = match method {
922+
hir::TraitMethod::Required([ident, ..]) => {
923+
ident.name == kw::SelfLower
924+
}
925+
hir::TraitMethod::Provided(body_id) => {
926+
match &self.tcx.hir().body(*body_id).params[..] {
927+
[hir::Param {
928+
pat:
929+
hir::Pat {
930+
kind:
931+
hir::PatKind::Binding(
932+
_,
933+
_,
934+
ident,
935+
..,
936+
),
937+
..
938+
},
939+
..
940+
}, ..] => ident.name == kw::SelfLower,
941+
_ => false,
942+
}
943+
}
944+
_ => false,
945+
};
946+
947+
if !fn_sig.decl.implicit_self.has_implicit_self()
948+
&& self_first_arg
949+
{
950+
if let Some(ty) = fn_sig.decl.inputs.get(0) {
951+
arbitrary_rcvr.push(ty.span);
952+
}
953+
return false;
954+
}
955+
}
956+
}
912957
// We only want to suggest public or local traits (#45781).
913958
item.vis == ty::Visibility::Public || info.def_id.is_local()
914959
})
915960
.is_some()
916961
})
917962
.collect::<Vec<_>>();
963+
for span in &arbitrary_rcvr {
964+
err.span_label(
965+
*span,
966+
"the method might not be found because of this arbitrary self type",
967+
);
968+
}
918969

919970
if !candidates.is_empty() {
920971
// Sort from most relevant to least relevant.

src/test/ui/issues/issue-5153.stderr

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
error[E0599]: no method named `foo` found for reference `&dyn Foo` in the current scope
22
--> $DIR/issue-5153.rs:10:27
33
|
4-
LL | trait Foo {
5-
| --------- `Foo` defines an item `foo`, perhaps you need to implement it
4+
LL | fn foo(self: Box<Self>);
5+
| --------- the method might not be found because of this arbitrary self type
66
...
77
LL | (&5isize as &dyn Foo).foo();
88
| ^^^ method not found in `&dyn Foo`
9-
|
10-
= help: items from traits can only be used if the trait is implemented and in scope
119

1210
error: aborting due to previous error
1311

src/test/ui/object-pointer-types.stderr

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,20 @@
11
error[E0599]: no method named `owned` found for reference `&dyn Foo` in the current scope
22
--> $DIR/object-pointer-types.rs:11:7
33
|
4-
LL | trait Foo {
5-
| --------- `Foo` defines an item `owned`, perhaps you need to implement it
4+
LL | fn owned(self: Box<Self>);
5+
| --------- the method might not be found because of this arbitrary self type
66
...
77
LL | x.owned();
88
| ^^^^^ method not found in `&dyn Foo`
9-
|
10-
= help: items from traits can only be used if the trait is implemented and in scope
119

1210
error[E0599]: no method named `owned` found for mutable reference `&mut dyn Foo` in the current scope
1311
--> $DIR/object-pointer-types.rs:17:7
1412
|
15-
LL | trait Foo {
16-
| --------- `Foo` defines an item `owned`, perhaps you need to implement it
13+
LL | fn owned(self: Box<Self>);
14+
| --------- the method might not be found because of this arbitrary self type
1715
...
1816
LL | x.owned();
1917
| ^^^^^ method not found in `&mut dyn Foo`
20-
|
21-
= help: items from traits can only be used if the trait is implemented and in scope
2218

2319
error[E0599]: no method named `managed` found for struct `std::boxed::Box<(dyn Foo + 'static)>` in the current scope
2420
--> $DIR/object-pointer-types.rs:23:7

src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,14 @@ error[E0599]: no method named `foo` found for struct `A` in the current scope
22
--> $DIR/point-at-arbitrary-self-type-trait-method.rs:9:7
33
|
44
LL | trait B { fn foo(self: Box<Self>); }
5-
| ------- --- the method is available for `std::boxed::Box<A>` here
6-
| |
7-
| `B` defines an item `foo`, perhaps you need to implement it
5+
| --- --------- the method might not be found because of this arbitrary self type
6+
| |
7+
| the method is available for `std::boxed::Box<A>` here
88
LL | struct A;
99
| --------- method `foo` not found for this
1010
...
1111
LL | A.foo()
1212
| ^^^ method not found in `A`
13-
|
14-
= help: items from traits can only be used if the trait is implemented and in scope
1513

1614
error: aborting due to previous error
1715

0 commit comments

Comments
 (0)