about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_typeck/src/check/expr.rs35
-rw-r--r--compiler/rustc_typeck/src/check/method/mod.rs2
-rw-r--r--src/test/ui/async-await/pin-needed-to-poll.rs47
-rw-r--r--src/test/ui/async-await/pin-needed-to-poll.stderr25
-rw-r--r--src/test/ui/copy-a-resource.stderr8
-rw-r--r--src/test/ui/derives/derive-assoc-type-not-impl.stderr8
-rw-r--r--src/test/ui/issues/issue-2823.stderr8
-rw-r--r--src/test/ui/issues/issue-69725.stderr8
-rw-r--r--src/test/ui/non-copyable-void.stderr8
-rw-r--r--src/test/ui/noncopyable-class.stderr8
-rw-r--r--src/test/ui/self/point-at-arbitrary-self-type-method.stderr5
-rw-r--r--src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr5
-rw-r--r--src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr11
-rw-r--r--src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr8
-rw-r--r--src/test/ui/union/union-derive-clone.stderr8
-rw-r--r--src/test/ui/unique-object-noncopyable.stderr8
-rw-r--r--src/test/ui/unique-pinned-nocopy.stderr8
17 files changed, 113 insertions, 97 deletions
diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs
index 8951c08bd33..9a2e933eb0b 100644
--- a/compiler/rustc_typeck/src/check/expr.rs
+++ b/compiler/rustc_typeck/src/check/expr.rs
@@ -973,7 +973,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         error: MethodError<'tcx>,
     ) {
         let rcvr = &args[0];
-        let try_alt_rcvr = |err: &mut DiagnosticBuilder<'_>, new_rcvr_t| {
+        let try_alt_rcvr = |err: &mut DiagnosticBuilder<'_>, new_rcvr_t, pre: &str, post: &str| {
             if let Some(new_rcvr_t) = new_rcvr_t {
                 if let Ok(pick) = self.lookup_probe(
                     span,
@@ -986,11 +986,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     // 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`
-                    if pick.autoderefs == 0 {
+                    if pick.autoderefs == 0
+                        // We don't want to suggest a container type when the missing method is
+                        // `.clone()`, otherwise we'd suggest `Arc::new(foo).clone()`, which is
+                        // far from what the user really wants.
+                        && Some(pick.item.container.id()) != self.tcx.lang_items().clone_trait()
+                    {
                         err.span_label(
                             pick.item.ident.span,
                             &format!("the method is available for `{}` here", new_rcvr_t),
                         );
+                        err.multipart_suggestion(
+                            "consider wrapping the receiver expression with the appropriate type",
+                            vec![
+                                (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
+                                (rcvr.span.shrink_to_hi(), ")".to_string()),
+                            ],
+                            Applicability::MaybeIncorrect,
+                        );
                     }
                 }
             }
@@ -1008,10 +1021,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // 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.
-                try_alt_rcvr(&mut err, self.tcx.mk_lang_item(rcvr_t, LangItem::OwnedBox));
-                try_alt_rcvr(&mut err, self.tcx.mk_lang_item(rcvr_t, LangItem::Pin));
-                try_alt_rcvr(&mut err, self.tcx.mk_diagnostic_item(rcvr_t, sym::Arc));
-                try_alt_rcvr(&mut err, self.tcx.mk_diagnostic_item(rcvr_t, sym::Rc));
+                for (rcvr_t, post) in &[
+                    (rcvr_t, ""),
+                    (self.tcx.mk_mut_ref(&ty::ReErased, rcvr_t), "&mut "),
+                    (self.tcx.mk_imm_ref(&ty::ReErased, rcvr_t), "&"),
+                ] {
+                    for (rcvr_t, pre) in &[
+                        (self.tcx.mk_lang_item(rcvr_t, LangItem::OwnedBox), "Box::new"),
+                        (self.tcx.mk_lang_item(rcvr_t, LangItem::Pin), "Pin::new"),
+                        (self.tcx.mk_diagnostic_item(rcvr_t, sym::Arc), "Arc::new"),
+                        (self.tcx.mk_diagnostic_item(rcvr_t, sym::Rc), "Rc::new"),
+                    ] {
+                        try_alt_rcvr(&mut err, *rcvr_t, pre, post);
+                    }
+                }
             }
             err.emit();
         }
diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs
index d6fa6bf0067..c74fd25f76d 100644
--- a/compiler/rustc_typeck/src/check/method/mod.rs
+++ b/compiler/rustc_typeck/src/check/method/mod.rs
@@ -45,6 +45,7 @@ pub struct MethodCallee<'tcx> {
     pub sig: ty::FnSig<'tcx>,
 }
 
+#[derive(Debug)]
 pub enum MethodError<'tcx> {
     // Did not find an applicable method, but we did find various near-misses that may work.
     NoMatch(NoMatchData<'tcx>),
@@ -66,6 +67,7 @@ pub enum MethodError<'tcx> {
 
 // Contains a list of static methods that may apply, a list of unsatisfied trait predicates which
 // could lead to matches if satisfied, and a list of not-in-scope traits which may work.
+#[derive(Debug)]
 pub struct NoMatchData<'tcx> {
     pub static_candidates: Vec<CandidateSource>,
     pub unsatisfied_predicates: Vec<(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>)>,
diff --git a/src/test/ui/async-await/pin-needed-to-poll.rs b/src/test/ui/async-await/pin-needed-to-poll.rs
new file mode 100644
index 00000000000..0d1fe684f60
--- /dev/null
+++ b/src/test/ui/async-await/pin-needed-to-poll.rs
@@ -0,0 +1,47 @@
+use std::{
+    future::Future,
+    pin::Pin,
+    task::{Context, Poll},
+};
+
+struct Sleep;
+
+impl Future for Sleep {
+    type Output = ();
+
+    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        Poll::Ready(())
+    }
+}
+
+impl Drop for Sleep {
+    fn drop(&mut self) {}
+}
+
+fn sleep() -> Sleep {
+    Sleep
+}
+
+
+struct MyFuture {
+    sleep: Sleep,
+}
+
+impl MyFuture {
+    fn new() -> Self {
+        Self {
+            sleep: sleep(),
+        }
+    }
+}
+
+impl Future for MyFuture {
+    type Output = ();
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+        self.sleep.poll(cx)
+        //~^ ERROR no method named `poll` found for struct `Sleep` in the current scope
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/pin-needed-to-poll.stderr b/src/test/ui/async-await/pin-needed-to-poll.stderr
new file mode 100644
index 00000000000..0e3716d6156
--- /dev/null
+++ b/src/test/ui/async-await/pin-needed-to-poll.stderr
@@ -0,0 +1,25 @@
+error[E0599]: no method named `poll` found for struct `Sleep` in the current scope
+  --> $DIR/pin-needed-to-poll.rs:42:20
+   |
+LL | struct Sleep;
+   | ------------- method `poll` not found for this
+...
+LL |         self.sleep.poll(cx)
+   |                    ^^^^ method not found in `Sleep`
+   | 
+  ::: $SRC_DIR/core/src/future/future.rs:LL:COL
+   |
+LL |     fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
+   |        ---- the method is available for `Pin<&mut Sleep>` here
+   |
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `poll`, perhaps you need to implement it:
+           candidate #1: `Future`
+help: consider wrapping the receiver expression with the appropriate type
+   |
+LL |         Pin::new(&mut self.sleep).poll(cx)
+   |         ^^^^^^^^^^^^^           ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/copy-a-resource.stderr b/src/test/ui/copy-a-resource.stderr
index 36cf57bd3c5..79095452f9d 100644
--- a/src/test/ui/copy-a-resource.stderr
+++ b/src/test/ui/copy-a-resource.stderr
@@ -6,14 +6,6 @@ LL | struct Foo {
 ...
 LL |     let _y = x.clone();
    |                ^^^^^ method not found in `Foo`
-   | 
-  ::: $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL |     fn clone(&self) -> Self;
-   |        -----
-   |        |
-   |        the method is available for `Arc<Foo>` here
-   |        the method is available for `Rc<Foo>` here
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `clone`, perhaps you need to implement it:
diff --git a/src/test/ui/derives/derive-assoc-type-not-impl.stderr b/src/test/ui/derives/derive-assoc-type-not-impl.stderr
index ffee7004f8f..fd993d0f9d8 100644
--- a/src/test/ui/derives/derive-assoc-type-not-impl.stderr
+++ b/src/test/ui/derives/derive-assoc-type-not-impl.stderr
@@ -12,14 +12,6 @@ LL | struct NotClone;
 ...
 LL |     Bar::<NotClone> { x: 1 }.clone();
    |                              ^^^^^ method cannot be called on `Bar<NotClone>` due to unsatisfied trait bounds
-   | 
-  ::: $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL |     fn clone(&self) -> Self;
-   |        -----
-   |        |
-   |        the method is available for `Arc<Bar<NotClone>>` here
-   |        the method is available for `Rc<Bar<NotClone>>` here
    |
    = note: the following trait bounds were not satisfied:
            `NotClone: Clone`
diff --git a/src/test/ui/issues/issue-2823.stderr b/src/test/ui/issues/issue-2823.stderr
index e044352e954..b3bc946292f 100644
--- a/src/test/ui/issues/issue-2823.stderr
+++ b/src/test/ui/issues/issue-2823.stderr
@@ -6,14 +6,6 @@ LL | struct C {
 ...
 LL |     let _d = c.clone();
    |                ^^^^^ method not found in `C`
-   | 
-  ::: $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL |     fn clone(&self) -> Self;
-   |        -----
-   |        |
-   |        the method is available for `Arc<C>` here
-   |        the method is available for `Rc<C>` here
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `clone`, perhaps you need to implement it:
diff --git a/src/test/ui/issues/issue-69725.stderr b/src/test/ui/issues/issue-69725.stderr
index 48c71d76af0..4dd6b4bbb68 100644
--- a/src/test/ui/issues/issue-69725.stderr
+++ b/src/test/ui/issues/issue-69725.stderr
@@ -8,14 +8,6 @@ LL |     let _ = Struct::<A>::new().clone();
    |
 LL | pub struct Struct<A>(A);
    | ------------------------ doesn't satisfy `Struct<A>: Clone`
-   | 
-  ::: $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL |     fn clone(&self) -> Self;
-   |        -----
-   |        |
-   |        the method is available for `Arc<Struct<A>>` here
-   |        the method is available for `Rc<Struct<A>>` here
    |
    = note: the following trait bounds were not satisfied:
            `A: Clone`
diff --git a/src/test/ui/non-copyable-void.stderr b/src/test/ui/non-copyable-void.stderr
index 8395a3a0563..99af04e7cd9 100644
--- a/src/test/ui/non-copyable-void.stderr
+++ b/src/test/ui/non-copyable-void.stderr
@@ -3,14 +3,6 @@ error[E0599]: no method named `clone` found for enum `c_void` in the current sco
    |
 LL |         let _z = (*y).clone();
    |                       ^^^^^ method not found in `c_void`
-   | 
-  ::: $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL |     fn clone(&self) -> Self;
-   |        -----
-   |        |
-   |        the method is available for `Arc<c_void>` here
-   |        the method is available for `Rc<c_void>` here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/noncopyable-class.stderr b/src/test/ui/noncopyable-class.stderr
index b8e467d8402..4674c16eb43 100644
--- a/src/test/ui/noncopyable-class.stderr
+++ b/src/test/ui/noncopyable-class.stderr
@@ -6,14 +6,6 @@ LL | struct Foo {
 ...
 LL |     let _y = x.clone();
    |                ^^^^^ method not found in `Foo`
-   | 
-  ::: $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL |     fn clone(&self) -> Self;
-   |        -----
-   |        |
-   |        the method is available for `Arc<Foo>` here
-   |        the method is available for `Rc<Foo>` here
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `clone`, perhaps you need to implement it:
diff --git a/src/test/ui/self/point-at-arbitrary-self-type-method.stderr b/src/test/ui/self/point-at-arbitrary-self-type-method.stderr
index 2954a499c18..b804ddfb024 100644
--- a/src/test/ui/self/point-at-arbitrary-self-type-method.stderr
+++ b/src/test/ui/self/point-at-arbitrary-self-type-method.stderr
@@ -9,6 +9,11 @@ LL |     fn foo(self: Box<Self>) {}
 ...
 LL |     A.foo();
    |       ^^^ method not found in `A`
+   |
+help: consider wrapping the receiver expression with the appropriate type
+   |
+LL |     Box::new(A).foo();
+   |     ^^^^^^^^^ ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr
index 89fe84c0d2d..e1ed0e42f98 100644
--- a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr
+++ b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr
@@ -10,6 +10,11 @@ LL | struct A;
 ...
 LL |     A.foo()
    |       ^^^ method not found in `A`
+   |
+help: consider wrapping the receiver expression with the appropriate type
+   |
+LL |     Box::new(A).foo()
+   |     ^^^^^^^^^ ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr
deleted file mode 100644
index 916a6c2bf12..00000000000
--- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0261]: use of undeclared lifetime name `'a`
-  --> $DIR/missing-lifetimes-in-signature.rs:36:11
-   |
-LL | fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
-   |        -  ^^ undeclared lifetime
-   |        |
-   |        help: consider introducing lifetime `'a` here: `'a,`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0261`.
diff --git a/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr b/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr
index d39daaba206..01e36a4a62a 100644
--- a/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr
+++ b/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr
@@ -6,14 +6,6 @@ LL | struct Qux;
 ...
 LL |     Qux.clone();
    |         ^^^^^ method not found in `Qux`
-   | 
-  ::: $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL |     fn clone(&self) -> Self;
-   |        -----
-   |        |
-   |        the method is available for `Arc<Qux>` here
-   |        the method is available for `Rc<Qux>` here
    |
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the trait `Clone` defines an item `clone`, but is explicitely unimplemented
diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.stderr
index a793bf58d23..546394664df 100644
--- a/src/test/ui/union/union-derive-clone.stderr
+++ b/src/test/ui/union/union-derive-clone.stderr
@@ -25,14 +25,6 @@ LL | struct CloneNoCopy;
 ...
 LL |     let w = u.clone();
    |               ^^^^^ method cannot be called on `U5<CloneNoCopy>` due to unsatisfied trait bounds
-   | 
-  ::: $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL |     fn clone(&self) -> Self;
-   |        -----
-   |        |
-   |        the method is available for `Arc<U5<CloneNoCopy>>` here
-   |        the method is available for `Rc<U5<CloneNoCopy>>` here
    |
    = note: the following trait bounds were not satisfied:
            `CloneNoCopy: Copy`
diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr
index 4bbacfc0a8b..6a355dd2562 100644
--- a/src/test/ui/unique-object-noncopyable.stderr
+++ b/src/test/ui/unique-object-noncopyable.stderr
@@ -10,14 +10,6 @@ LL |   trait Foo {
 LL |       let _z = y.clone();
    |                  ^^^^^ method cannot be called on `Box<dyn Foo>` due to unsatisfied trait bounds
    | 
-  ::: $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL |       fn clone(&self) -> Self;
-   |          -----
-   |          |
-   |          the method is available for `Arc<Box<dyn Foo>>` here
-   |          the method is available for `Rc<Box<dyn Foo>>` here
-   | 
   ::: $SRC_DIR/alloc/src/boxed.rs:LL:COL
    |
 LL | / pub struct Box<
diff --git a/src/test/ui/unique-pinned-nocopy.stderr b/src/test/ui/unique-pinned-nocopy.stderr
index dd0b7fc5489..a4421bcf809 100644
--- a/src/test/ui/unique-pinned-nocopy.stderr
+++ b/src/test/ui/unique-pinned-nocopy.stderr
@@ -7,14 +7,6 @@ LL |   struct R {
 LL |       let _j = i.clone();
    |                  ^^^^^ method cannot be called on `Box<R>` due to unsatisfied trait bounds
    | 
-  ::: $SRC_DIR/core/src/clone.rs:LL:COL
-   |
-LL |       fn clone(&self) -> Self;
-   |          -----
-   |          |
-   |          the method is available for `Arc<Box<R>>` here
-   |          the method is available for `Rc<Box<R>>` here
-   | 
   ::: $SRC_DIR/alloc/src/boxed.rs:LL:COL
    |
 LL | / pub struct Box<