Rollup merge of #84499 - estebank:issue-84272, r=jackh726
Tweak trait not `use`d suggestion Fix #84272. Follow up to #83667.
This commit is contained in:
commit
ae316d6603
10 changed files with 96 additions and 8 deletions
|
@ -988,6 +988,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
let mut alt_rcvr_sugg = false;
|
let mut alt_rcvr_sugg = false;
|
||||||
if let SelfSource::MethodCall(rcvr) = source {
|
if let SelfSource::MethodCall(rcvr) = source {
|
||||||
debug!(?span, ?item_name, ?rcvr_ty, ?rcvr);
|
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.
|
// Try alternative arbitrary self types that could fulfill this call.
|
||||||
// FIXME: probe for all types that *could* be arbitrary self-types, not
|
// FIXME: probe for all types that *could* be arbitrary self-types, not
|
||||||
// just this list.
|
// just this list.
|
||||||
|
@ -996,6 +1002,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
(self.tcx.mk_mut_ref(&ty::ReErased, rcvr_ty), "&mut "),
|
(self.tcx.mk_mut_ref(&ty::ReErased, rcvr_ty), "&mut "),
|
||||||
(self.tcx.mk_imm_ref(&ty::ReErased, rcvr_ty), "&"),
|
(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),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
for (rcvr_ty, pre) in &[
|
for (rcvr_ty, pre) in &[
|
||||||
(self.tcx.mk_lang_item(rcvr_ty, LangItem::OwnedBox), "Box::new"),
|
(self.tcx.mk_lang_item(rcvr_ty, LangItem::OwnedBox), "Box::new"),
|
||||||
(self.tcx.mk_lang_item(rcvr_ty, LangItem::Pin), "Pin::new"),
|
(self.tcx.mk_lang_item(rcvr_ty, LangItem::Pin), "Pin::new"),
|
||||||
|
@ -1015,13 +1042,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
// We don't want to suggest a container type when the missing
|
// We don't want to suggest a container type when the missing
|
||||||
// method is `.clone()` or `.deref()` otherwise we'd suggest
|
// method is `.clone()` or `.deref()` otherwise we'd suggest
|
||||||
// `Arc::new(foo).clone()`, which is far from what the user wants.
|
// `Arc::new(foo).clone()`, which is far from what the user wants.
|
||||||
let skip = [
|
let skip = skippable.contains(&did);
|
||||||
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);
|
|
||||||
// Make sure the method is defined for the *actual* receiver: we don't
|
// 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
|
// want to treat `Box<Self>` as a receiver if it only works because of
|
||||||
// an autoderef to `&self`
|
// an autoderef to `&self`
|
||||||
|
@ -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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
error[E0599]: no method named `f` found for unit type `()` in the current scope
|
error[E0599]: no method named `f` found for unit type `()` in the current scope
|
||||||
--> $DIR/trait_items.rs:17:24
|
--> $DIR/trait_items.rs:17:24
|
||||||
|
|
|
|
||||||
|
LL | fn f(&self) {}
|
||||||
|
| - the method is available for `()` here
|
||||||
|
...
|
||||||
LL | fn f() { ::baz::m!(); }
|
LL | fn f() { ::baz::m!(); }
|
||||||
| ------------ in this macro invocation
|
| ------------ in this macro invocation
|
||||||
...
|
...
|
||||||
|
|
|
@ -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
|
error[E0599]: no method named `method` found for type `char` in the current scope
|
||||||
--> $DIR/no-method-suggested-traits.rs:30:9
|
--> $DIR/no-method-suggested-traits.rs:30:9
|
||||||
|
|
|
|
||||||
|
LL | fn method(&self) {}
|
||||||
|
| ------ the method is available for `char` here
|
||||||
|
...
|
||||||
LL | 'a'.method();
|
LL | 'a'.method();
|
||||||
| ^^^^^^ method not found in `char`
|
| ^^^^^^ method not found in `char`
|
||||||
|
|
|
|
||||||
|
@ -64,6 +67,11 @@ error[E0599]: no method named `method` found for type `i32` in the current scope
|
||||||
LL | 1i32.method();
|
LL | 1i32.method();
|
||||||
| ^^^^^^ method not found in `i32`
|
| ^^^^^^ 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: 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:
|
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
||||||
|
|
|
|
||||||
|
|
|
@ -4,6 +4,11 @@ error[E0599]: no method named `a` found for unit type `()` in the current scope
|
||||||
LL | ().a();
|
LL | ().a();
|
||||||
| ^ method not found in `()`
|
| ^ 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: 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:
|
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
||||||
|
|
|
|
||||||
|
|
|
@ -4,6 +4,11 @@ error[E0599]: no method named `trait_method` found for struct `FooStruct` in the
|
||||||
LL | reexported_trait::FooStruct.trait_method();
|
LL | reexported_trait::FooStruct.trait_method();
|
||||||
| ^^^^^^^^^^^^ method not found in `FooStruct`
|
| ^^^^^^^^^^^^ 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: 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:
|
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
||||||
|
|
|
|
||||||
|
@ -16,6 +21,11 @@ error[E0599]: no method named `trait_method_b` found for struct `FooStruct` in t
|
||||||
LL | reexported_trait::FooStruct.trait_method_b();
|
LL | reexported_trait::FooStruct.trait_method_b();
|
||||||
| ^^^^^^^^^^^^^^ method not found in `FooStruct`
|
| ^^^^^^^^^^^^^^ 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: 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:
|
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
||||||
|
|
|
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
error[E0599]: no method named `foobar` found for type `u32` in the current scope
|
error[E0599]: no method named `foobar` found for type `u32` in the current scope
|
||||||
--> $DIR/trait-import-suggestions.rs:22:11
|
--> $DIR/trait-import-suggestions.rs:22:11
|
||||||
|
|
|
|
||||||
|
LL | fn foobar(&self) { }
|
||||||
|
| ------ the method is available for `u32` here
|
||||||
|
...
|
||||||
LL | x.foobar();
|
LL | x.foobar();
|
||||||
| ^^^^^^ method not found in `u32`
|
| ^^^^^^ method not found in `u32`
|
||||||
|
|
|
|
||||||
|
@ -11,6 +14,9 @@ LL | x.foobar();
|
||||||
error[E0599]: no method named `bar` found for type `u32` in the current scope
|
error[E0599]: no method named `bar` found for type `u32` in the current scope
|
||||||
--> $DIR/trait-import-suggestions.rs:28:7
|
--> $DIR/trait-import-suggestions.rs:28:7
|
||||||
|
|
|
|
||||||
|
LL | fn bar(&self) { }
|
||||||
|
| --- the method is available for `u32` here
|
||||||
|
...
|
||||||
LL | x.bar();
|
LL | x.bar();
|
||||||
| ^^^ method not found in `u32`
|
| ^^^ method not found in `u32`
|
||||||
|
|
|
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
error[E0599]: no method named `f` found for unit type `()` in the current scope
|
error[E0599]: no method named `f` found for unit type `()` in the current scope
|
||||||
--> $DIR/shadowed-trait-methods.rs:13:8
|
--> $DIR/shadowed-trait-methods.rs:13:8
|
||||||
|
|
|
|
||||||
|
LL | pub trait T { fn f(&self) {} }
|
||||||
|
| - the method is available for `()` here
|
||||||
|
...
|
||||||
LL | ().f()
|
LL | ().f()
|
||||||
| ^ method not found in `()`
|
| ^ method not found in `()`
|
||||||
|
|
|
|
||||||
|
|
9
src/test/ui/suggestions/import-trait-for-method-call.rs
Normal file
9
src/test/ui/suggestions/import-trait-for-method-call.rs
Normal file
|
@ -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
src/test/ui/suggestions/import-trait-for-method-call.stderr
Normal file
20
src/test/ui/suggestions/import-trait-for-method-call.stderr
Normal file
|
@ -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`.
|
|
@ -20,6 +20,9 @@ error[E0599]: no method named `b` found for struct `S` in the current scope
|
||||||
LL | struct S;
|
LL | struct S;
|
||||||
| --------- method `b` not found for this
|
| --------- method `b` not found for this
|
||||||
...
|
...
|
||||||
|
LL | fn b(&self) { }
|
||||||
|
| - the method is available for `S` here
|
||||||
|
...
|
||||||
LL | S.b();
|
LL | S.b();
|
||||||
| ^ method not found in `S`
|
| ^ method not found in `S`
|
||||||
|
|
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue