Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tweak trait not used suggestion #84499

Merged
merged 3 commits into from
Apr 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 29 additions & 8 deletions compiler/rustc_typeck/src/check/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -988,6 +988,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut alt_rcvr_sugg = false;
if let SelfSource::MethodCall(rcvr) = source {
debug!(?span, ?item_name, ?rcvr_ty, ?rcvr);
let skippable = [
self.tcx.lang_items().clone_trait(),
self.tcx.lang_items().deref_trait(),
self.tcx.lang_items().deref_mut_trait(),
self.tcx.lang_items().drop_trait(),
];
// Try alternative arbitrary self types that could fulfill this call.
// FIXME: probe for all types that *could* be arbitrary self-types, not
// just this list.
Expand All @@ -996,6 +1002,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
(self.tcx.mk_mut_ref(&ty::ReErased, rcvr_ty), "&mut "),
(self.tcx.mk_imm_ref(&ty::ReErased, rcvr_ty), "&"),
] {
if let Ok(pick) = self.lookup_probe(
span,
item_name,
rcvr_ty,
rcvr,
crate::check::method::probe::ProbeScope::AllTraits,
) {
// If the method is defined for the receiver we have, it likely wasn't `use`d.
// We point at the method, but we just skip the rest of the check for arbitrary
// self types and rely on the suggestion to `use` the trait from
// `suggest_valid_traits`.
let did = Some(pick.item.container.id());
let skip = skippable.contains(&did);
if pick.autoderefs == 0 && !skip {
err.span_label(
pick.item.ident.span,
&format!("the method is available for `{}` here", rcvr_ty),
);
Comment on lines +1019 to +1022
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm really not sure how useful this is...imo the module/use statement is enough.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it helps a little bit when in concert with the suggestion, because the suggestion text doesn't explain why importing that trait would be enough.

}
break;
}
for (rcvr_ty, pre) in &[
(self.tcx.mk_lang_item(rcvr_ty, LangItem::OwnedBox), "Box::new"),
(self.tcx.mk_lang_item(rcvr_ty, LangItem::Pin), "Pin::new"),
Expand All @@ -1015,13 +1042,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// We don't want to suggest a container type when the missing
// method is `.clone()` or `.deref()` otherwise we'd suggest
// `Arc::new(foo).clone()`, which is far from what the user wants.
let skip = [
self.tcx.lang_items().clone_trait(),
self.tcx.lang_items().deref_trait(),
self.tcx.lang_items().deref_mut_trait(),
self.tcx.lang_items().drop_trait(),
]
.contains(&did);
let skip = skippable.contains(&did);
// Make sure the method is defined for the *actual* receiver: we don't
// want to treat `Box<Self>` as a receiver if it only works because of
// an autoderef to `&self`
Expand All @@ -1047,7 +1068,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
}
if !alt_rcvr_sugg && self.suggest_valid_traits(err, valid_out_of_scope_traits) {
if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
return;
}

Expand Down
3 changes: 3 additions & 0 deletions src/test/ui/hygiene/trait_items.stderr
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
error[E0599]: no method named `f` found for unit type `()` in the current scope
--> $DIR/trait_items.rs:17:24
|
LL | fn f(&self) {}
| - the method is available for `()` here
...
LL | fn f() { ::baz::m!(); }
| ------------ in this macro invocation
...
Expand Down
8 changes: 8 additions & 0 deletions src/test/ui/impl-trait/no-method-suggested-traits.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ LL | use no_method_suggested_traits::Reexported;
error[E0599]: no method named `method` found for type `char` in the current scope
--> $DIR/no-method-suggested-traits.rs:30:9
|
LL | fn method(&self) {}
| ------ the method is available for `char` here
...
LL | 'a'.method();
| ^^^^^^ method not found in `char`
|
Expand All @@ -63,6 +66,11 @@ error[E0599]: no method named `method` found for type `i32` in the current scope
|
LL | 1i32.method();
| ^^^^^^ method not found in `i32`
|
::: $DIR/auxiliary/no_method_suggested_traits.rs:8:12
|
LL | fn method(&self) {}
| ------ the method is available for `i32` here
|
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
Expand Down
5 changes: 5 additions & 0 deletions src/test/ui/issues/issue-43189.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ error[E0599]: no method named `a` found for unit type `()` in the current scope
|
LL | ().a();
| ^ method not found in `()`
|
::: $DIR/auxiliary/xcrate-issue-43189-a.rs:5:8
|
LL | fn a(&self) {}
| - the method is available for `()` here
|
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
Expand Down
10 changes: 10 additions & 0 deletions src/test/ui/issues/issue-56175.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ error[E0599]: no method named `trait_method` found for struct `FooStruct` in the
|
LL | reexported_trait::FooStruct.trait_method();
| ^^^^^^^^^^^^ method not found in `FooStruct`
|
::: $DIR/auxiliary/reexported-trait.rs:3:12
|
LL | fn trait_method(&self) {
| ------------ the method is available for `FooStruct` here
|
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
Expand All @@ -15,6 +20,11 @@ error[E0599]: no method named `trait_method_b` found for struct `FooStruct` in t
|
LL | reexported_trait::FooStruct.trait_method_b();
| ^^^^^^^^^^^^^^ method not found in `FooStruct`
|
::: $DIR/auxiliary/reexported-trait.rs:7:12
|
LL | fn trait_method_b(&self) {
| -------------- the method is available for `FooStruct` here
|
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
Expand Down
6 changes: 6 additions & 0 deletions src/test/ui/rust-2018/trait-import-suggestions.stderr
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
error[E0599]: no method named `foobar` found for type `u32` in the current scope
--> $DIR/trait-import-suggestions.rs:22:11
|
LL | fn foobar(&self) { }
| ------ the method is available for `u32` here
...
LL | x.foobar();
| ^^^^^^ method not found in `u32`
|
Expand All @@ -11,6 +14,9 @@ LL | x.foobar();
error[E0599]: no method named `bar` found for type `u32` in the current scope
--> $DIR/trait-import-suggestions.rs:28:7
|
LL | fn bar(&self) { }
| --- the method is available for `u32` here
...
LL | x.bar();
| ^^^ method not found in `u32`
|
Expand Down
3 changes: 3 additions & 0 deletions src/test/ui/shadowed/shadowed-trait-methods.stderr
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
error[E0599]: no method named `f` found for unit type `()` in the current scope
--> $DIR/shadowed-trait-methods.rs:13:8
|
LL | pub trait T { fn f(&self) {} }
| - the method is available for `()` here
...
LL | ().f()
| ^ method not found in `()`
|
Expand Down
9 changes: 9 additions & 0 deletions src/test/ui/suggestions/import-trait-for-method-call.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use std::hash::BuildHasher;

fn next_u64() -> u64 {
let bh = std::collections::hash_map::RandomState::new();
let h = bh.build_hasher();
h.finish() //~ ERROR no method named `finish` found for struct `DefaultHasher`
}

fn main() {}
20 changes: 20 additions & 0 deletions src/test/ui/suggestions/import-trait-for-method-call.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
error[E0599]: no method named `finish` found for struct `DefaultHasher` in the current scope
--> $DIR/import-trait-for-method-call.rs:6:7
|
LL | h.finish()
| ^^^^^^ method not found in `DefaultHasher`
|
::: $SRC_DIR/core/src/hash/mod.rs:LL:COL
|
LL | fn finish(&self) -> u64;
| ------ the method is available for `DefaultHasher` here
|
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
LL | use std::hash::Hasher;
|

error: aborting due to previous error

For more information about this error, try `rustc --explain E0599`.
3 changes: 3 additions & 0 deletions src/test/ui/traits/item-privacy.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ error[E0599]: no method named `b` found for struct `S` in the current scope
LL | struct S;
| --------- method `b` not found for this
...
LL | fn b(&self) { }
| - the method is available for `S` here
...
LL | S.b();
| ^ method not found in `S`
|
Expand Down