diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index cbbb47ecaae1c..3213148f6a3dc 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -1485,27 +1485,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (self.tcx.mk_mut_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "), (self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&"), ] { - if let Ok(pick) = self.lookup_probe( + match 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(self.tcx).span, - &format!("the method is available for `{}` here", rcvr_ty), - ); + Ok(pick) => { + // 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(self.tcx).span, + &format!("the method is available for `{}` here", rcvr_ty), + ); + } + break; } - break; + Err(MethodError::Ambiguity(_)) => { + // If the method is defined (but ambiguous) for the receiver we have, it is also + // likely we haven't `use`d it. It may be possible that if we `Box`/`Pin`/etc. + // the receiver, then it might disambiguate this method, but I think these + // suggestions are generally misleading (see #94218). + 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"), diff --git a/src/test/ui/rust-2021/future-prelude-collision-shadow.stderr b/src/test/ui/rust-2021/future-prelude-collision-shadow.stderr index d945b4c94ca2f..3d21b735aea0a 100644 --- a/src/test/ui/rust-2021/future-prelude-collision-shadow.stderr +++ b/src/test/ui/rust-2021/future-prelude-collision-shadow.stderr @@ -4,34 +4,8 @@ error[E0599]: no method named `try_into` found for type `u8` in the current scop LL | let _: u32 = 3u8.try_into().unwrap(); | ^^^^^^^^ method not found in `u8` | - ::: $SRC_DIR/core/src/convert/mod.rs:LL:COL - | -LL | fn try_into(self) -> Result; - | -------- - | | - | the method is available for `Box` here - | the method is available for `Pin` here - | the method is available for `Arc` here - | the method is available for `Rc` here - | = help: items from traits can only be used if the trait is in scope = note: 'std::convert::TryInto' is included in the prelude starting in Edition 2021 -help: consider wrapping the receiver expression with the appropriate type - | -LL | let _: u32 = Box::new(3u8).try_into().unwrap(); - | +++++++++ + -help: consider wrapping the receiver expression with the appropriate type - | -LL | let _: u32 = Pin::new(3u8).try_into().unwrap(); - | +++++++++ + -help: consider wrapping the receiver expression with the appropriate type - | -LL | let _: u32 = Arc::new(3u8).try_into().unwrap(); - | +++++++++ + -help: consider wrapping the receiver expression with the appropriate type - | -LL | let _: u32 = Rc::new(3u8).try_into().unwrap(); - | ++++++++ + help: the following traits are implemented but not in scope; perhaps add a `use` for one of them: | LL | use crate::m::TryIntoU32; diff --git a/src/test/ui/suggestions/dont-wrap-ambiguous-receivers.rs b/src/test/ui/suggestions/dont-wrap-ambiguous-receivers.rs new file mode 100644 index 0000000000000..baa2128eb8e36 --- /dev/null +++ b/src/test/ui/suggestions/dont-wrap-ambiguous-receivers.rs @@ -0,0 +1,21 @@ +mod banana { + //~^ HELP the following traits are implemented but not in scope + pub struct Chaenomeles; + + pub trait Apple { + fn pick(&self) {} + } + impl Apple for Chaenomeles {} + + pub trait Peach { + fn pick(&self, a: &mut ()) {} + } + impl Peach for Box {} + impl Peach for Chaenomeles {} +} + +fn main() { + banana::Chaenomeles.pick() + //~^ ERROR no method named + //~| HELP items from traits can only be used if the trait is in scope +} diff --git a/src/test/ui/suggestions/dont-wrap-ambiguous-receivers.stderr b/src/test/ui/suggestions/dont-wrap-ambiguous-receivers.stderr new file mode 100644 index 0000000000000..8fcadbf4c75f4 --- /dev/null +++ b/src/test/ui/suggestions/dont-wrap-ambiguous-receivers.stderr @@ -0,0 +1,20 @@ +error[E0599]: no method named `pick` found for struct `Chaenomeles` in the current scope + --> $DIR/dont-wrap-ambiguous-receivers.rs:18:25 + | +LL | pub struct Chaenomeles; + | ----------------------- method `pick` not found for this +... +LL | banana::Chaenomeles.pick() + | ^^^^ method not found in `Chaenomeles` + | + = help: items from traits can only be used if the trait is in scope +help: the following traits are implemented but not in scope; perhaps add a `use` for one of them: + | +LL | use banana::Apple; + | +LL | use banana::Peach; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`.