about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_typeck/src/check/method/suggest.rs37
-rw-r--r--src/test/ui/rust-2021/future-prelude-collision-shadow.stderr26
-rw-r--r--src/test/ui/suggestions/dont-wrap-ambiguous-receivers.rs21
-rw-r--r--src/test/ui/suggestions/dont-wrap-ambiguous-receivers.stderr20
4 files changed, 65 insertions, 39 deletions
diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs
index cbbb47ecaae..3213148f6a3 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 d945b4c94ca..3d21b735aea 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<T, Self::Error>;
-   |        --------
-   |        |
-   |        the method is available for `Box<u8>` here
-   |        the method is available for `Pin<u8>` here
-   |        the method is available for `Arc<u8>` here
-   |        the method is available for `Rc<u8>` 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 00000000000..baa2128eb8e
--- /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<Mango: Peach> Peach for Box<Mango> {}
+    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 00000000000..8fcadbf4c75
--- /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`.