about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2024-03-17 21:25:38 +0000
committerEsteban Küber <esteban@kuber.com.ar>2024-04-11 16:41:42 +0000
commitd97d2fe7440ea3032a93fa3ebf8d62fea0337d04 (patch)
tree84f778762a45c6c7820a0dcdd557292424e9d926
parentd578ac9e476a376246320db1d934972601c5b0f5 (diff)
downloadrust-d97d2fe7440ea3032a93fa3ebf8d62fea0337d04.tar.gz
rust-d97d2fe7440ea3032a93fa3ebf8d62fea0337d04.zip
Mention when the type of the moved value doesn't implement `Clone`
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs15
-rw-r--r--tests/ui/associated-types/issue-25700.stderr6
-rw-r--r--tests/ui/borrowck/borrowck-move-out-of-static-item.stderr6
-rw-r--r--tests/ui/borrowck/borrowck-move-subcomponent.stderr6
-rw-r--r--tests/ui/borrowck/borrowck-overloaded-call.stderr6
-rw-r--r--tests/ui/borrowck/clone-on-ref.stderr5
-rw-r--r--tests/ui/borrowck/issue-103624.stderr6
-rw-r--r--tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr5
-rw-r--r--tests/ui/borrowck/issue-17718-static-move.stderr5
-rw-r--r--tests/ui/borrowck/issue-20801.stderr20
-rw-r--r--tests/ui/borrowck/move-error-in-promoted-2.stderr6
-rw-r--r--tests/ui/borrowck/move-error-snippets.stderr5
-rw-r--r--tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr12
-rw-r--r--tests/ui/box/leak-alloc.stderr6
-rw-r--r--tests/ui/derives/deriving-with-repr-packed.stderr5
-rw-r--r--tests/ui/error-codes/E0504.stderr6
-rw-r--r--tests/ui/error-codes/E0505.stderr6
-rw-r--r--tests/ui/error-codes/E0507.stderr5
-rw-r--r--tests/ui/error-codes/E0508-fail.stderr5
-rw-r--r--tests/ui/error-codes/E0508.stderr5
-rw-r--r--tests/ui/error-codes/E0509.stderr5
-rw-r--r--tests/ui/issues/issue-17385.stderr12
-rw-r--r--tests/ui/mir/issue-102389.stderr6
-rw-r--r--tests/ui/moves/issue-72649-uninit-in-loop.rs4
-rw-r--r--tests/ui/moves/issue-72649-uninit-in-loop.stderr36
-rw-r--r--tests/ui/moves/move-fn-self-receiver.stderr11
-rw-r--r--tests/ui/moves/move-out-of-array-1.stderr6
-rw-r--r--tests/ui/nll/issue-21232-partial-init-and-use.stderr12
-rw-r--r--tests/ui/nll/move-errors.stderr31
-rw-r--r--tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr10
-rw-r--r--tests/ui/union/union-borrow-move-parent-sibling.stderr5
-rw-r--r--tests/ui/union/union-move.stderr10
-rw-r--r--tests/ui/variance/variance-issue-20533.stderr18
33 files changed, 299 insertions, 8 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index ee50e82d80d..860f8882ad3 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -1195,8 +1195,19 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         let ty = ty.peel_refs();
         if self.implements_clone(ty) {
             self.suggest_cloning_inner(err, ty, expr);
-            // } else {
-            //     err.note(format!("if `{ty}` implemented `Clone`, you could clone the value"));
+        } else if let ty::Adt(def, args) = ty.kind()
+            && def.did().as_local().is_some()
+            && def.variants().iter().all(|variant| {
+                variant
+                    .fields
+                    .iter()
+                    .all(|field| self.implements_clone(field.ty(self.infcx.tcx, args)))
+            })
+        {
+            err.span_note(
+                self.infcx.tcx.def_span(def.did()),
+                format!("if `{ty}` implemented `Clone`, you could clone the value"),
+            );
         }
     }
 
diff --git a/tests/ui/associated-types/issue-25700.stderr b/tests/ui/associated-types/issue-25700.stderr
index 4e432c0e702..fb0e63c207a 100644
--- a/tests/ui/associated-types/issue-25700.stderr
+++ b/tests/ui/associated-types/issue-25700.stderr
@@ -7,6 +7,12 @@ LL |     drop(t);
    |          - value moved here
 LL |     drop(t);
    |          ^ value used here after move
+   |
+note: if `S<()>` implemented `Clone`, you could clone the value
+  --> $DIR/issue-25700.rs:1:1
+   |
+LL | struct S<T: 'static>(#[allow(dead_code)] Option<&'static T>);
+   | ^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr b/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr
index c4530820be5..86bddacbdc7 100644
--- a/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr
+++ b/tests/ui/borrowck/borrowck-move-out-of-static-item.stderr
@@ -3,6 +3,12 @@ error[E0507]: cannot move out of static item `BAR`
    |
 LL |     test(BAR);
    |          ^^^ move occurs because `BAR` has type `Foo`, which does not implement the `Copy` trait
+   |
+note: if `Foo` implemented `Clone`, you could clone the value
+  --> $DIR/borrowck-move-out-of-static-item.rs:3:1
+   |
+LL | struct Foo {
+   | ^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/borrowck/borrowck-move-subcomponent.stderr b/tests/ui/borrowck/borrowck-move-subcomponent.stderr
index 8408d99156a..4d9477f8581 100644
--- a/tests/ui/borrowck/borrowck-move-subcomponent.stderr
+++ b/tests/ui/borrowck/borrowck-move-subcomponent.stderr
@@ -9,6 +9,12 @@ LL |   let S { x: ax } = a;
    |              ^^ move out of `a.x` occurs here
 LL |   f(pb);
    |     -- borrow later used here
+   |
+note: if `S` implemented `Clone`, you could clone the value
+  --> $DIR/borrowck-move-subcomponent.rs:6:1
+   |
+LL | struct S {
+   | ^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/borrowck/borrowck-overloaded-call.stderr b/tests/ui/borrowck/borrowck-overloaded-call.stderr
index 723b19f4124..1602058c183 100644
--- a/tests/ui/borrowck/borrowck-overloaded-call.stderr
+++ b/tests/ui/borrowck/borrowck-overloaded-call.stderr
@@ -29,6 +29,12 @@ LL |     s(" world".to_string());
    |     - value moved here
 LL |     s(" world".to_string());
    |     ^ value used here after move
+   |
+note: if `SFnOnce` implemented `Clone`, you could clone the value
+  --> $DIR/borrowck-overloaded-call.rs:41:1
+   |
+LL | struct SFnOnce {
+   | ^^^^^^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/borrowck/clone-on-ref.stderr b/tests/ui/borrowck/clone-on-ref.stderr
index ee4fcadf55a..f0eaf4bac7d 100644
--- a/tests/ui/borrowck/clone-on-ref.stderr
+++ b/tests/ui/borrowck/clone-on-ref.stderr
@@ -52,6 +52,11 @@ LL |
 LL |     println!("{b:?}");
    |               ----- borrow later used here
    |
+note: if `A` implemented `Clone`, you could clone the value
+  --> $DIR/clone-on-ref.rs:19:1
+   |
+LL | struct A;
+   | ^^^^^^^^
 help: consider annotating `A` with `#[derive(Clone)]`
    |
 LL + #[derive(Clone)]
diff --git a/tests/ui/borrowck/issue-103624.stderr b/tests/ui/borrowck/issue-103624.stderr
index 7a281e8aa30..94421c35c65 100644
--- a/tests/ui/borrowck/issue-103624.stderr
+++ b/tests/ui/borrowck/issue-103624.stderr
@@ -9,6 +9,12 @@ LL |         spawn_blocking(move || {
 LL |
 LL |             self.b;
    |             ^^^^^^ move occurs because `self.b` has type `StructB`, which does not implement the `Copy` trait
+   |
+note: if `StructB` implemented `Clone`, you could clone the value
+  --> $DIR/issue-103624.rs:23:1
+   |
+LL | struct StructB {}
+   | ^^^^^^^^^^^^^^
 
 error[E0521]: borrowed data escapes outside of method
   --> $DIR/issue-103624.rs:14:9
diff --git a/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr b/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr
index ab42205d510..701f00d079d 100644
--- a/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr
+++ b/tests/ui/borrowck/issue-119915-bad-clone-suggestion.stderr
@@ -11,6 +11,11 @@ note: `Example::<E, FakeParam>::change` takes ownership of the receiver `self`,
    |
 LL |     unsafe fn change<NewFakeParam>(self) -> Example<E, NewFakeParam> {
    |                                    ^^^^
+note: if `Example<E, NoLifetime>` implemented `Clone`, you could clone the value
+  --> $DIR/issue-119915-bad-clone-suggestion.rs:3:1
+   |
+LL | struct Example<E, FakeParam>(PhantomData<(fn(E), fn(FakeParam))>);
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/borrowck/issue-17718-static-move.stderr b/tests/ui/borrowck/issue-17718-static-move.stderr
index 5ca0a7fb885..e2c3a9d5a26 100644
--- a/tests/ui/borrowck/issue-17718-static-move.stderr
+++ b/tests/ui/borrowck/issue-17718-static-move.stderr
@@ -4,6 +4,11 @@ error[E0507]: cannot move out of static item `FOO`
 LL |     let _a = FOO;
    |              ^^^ move occurs because `FOO` has type `Foo`, which does not implement the `Copy` trait
    |
+note: if `Foo` implemented `Clone`, you could clone the value
+  --> $DIR/issue-17718-static-move.rs:1:1
+   |
+LL | struct Foo;
+   | ^^^^^^^^^^
 help: consider borrowing here
    |
 LL |     let _a = &FOO;
diff --git a/tests/ui/borrowck/issue-20801.stderr b/tests/ui/borrowck/issue-20801.stderr
index 97294afd3df..1da6f0bef02 100644
--- a/tests/ui/borrowck/issue-20801.stderr
+++ b/tests/ui/borrowck/issue-20801.stderr
@@ -19,6 +19,11 @@ error[E0507]: cannot move out of a mutable reference
 LL |     let a = unsafe { *mut_ref() };
    |                      ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait
    |
+note: if `T` implemented `Clone`, you could clone the value
+  --> $DIR/issue-20801.rs:3:1
+   |
+LL | struct T(u8);
+   | ^^^^^^^^
 help: consider removing the dereference here
    |
 LL -     let a = unsafe { *mut_ref() };
@@ -31,6 +36,11 @@ error[E0507]: cannot move out of a shared reference
 LL |     let b = unsafe { *imm_ref() };
    |                      ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait
    |
+note: if `T` implemented `Clone`, you could clone the value
+  --> $DIR/issue-20801.rs:3:1
+   |
+LL | struct T(u8);
+   | ^^^^^^^^
 help: consider removing the dereference here
    |
 LL -     let b = unsafe { *imm_ref() };
@@ -43,6 +53,11 @@ error[E0507]: cannot move out of a raw pointer
 LL |     let c = unsafe { *mut_ptr() };
    |                      ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait
    |
+note: if `T` implemented `Clone`, you could clone the value
+  --> $DIR/issue-20801.rs:3:1
+   |
+LL | struct T(u8);
+   | ^^^^^^^^
 help: consider removing the dereference here
    |
 LL -     let c = unsafe { *mut_ptr() };
@@ -55,6 +70,11 @@ error[E0507]: cannot move out of a raw pointer
 LL |     let d = unsafe { *const_ptr() };
    |                      ^^^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait
    |
+note: if `T` implemented `Clone`, you could clone the value
+  --> $DIR/issue-20801.rs:3:1
+   |
+LL | struct T(u8);
+   | ^^^^^^^^
 help: consider removing the dereference here
    |
 LL -     let d = unsafe { *const_ptr() };
diff --git a/tests/ui/borrowck/move-error-in-promoted-2.stderr b/tests/ui/borrowck/move-error-in-promoted-2.stderr
index 0d5edadcb46..43f4e820857 100644
--- a/tests/ui/borrowck/move-error-in-promoted-2.stderr
+++ b/tests/ui/borrowck/move-error-in-promoted-2.stderr
@@ -6,6 +6,12 @@ LL |     &([S][0],);
    |       |
    |       cannot move out of here
    |       move occurs because value has type `S`, which does not implement the `Copy` trait
+   |
+note: if `S` implemented `Clone`, you could clone the value
+  --> $DIR/move-error-in-promoted-2.rs:3:1
+   |
+LL | struct S;
+   | ^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/borrowck/move-error-snippets.stderr b/tests/ui/borrowck/move-error-snippets.stderr
index 83f9e19aa0d..40b64398aef 100644
--- a/tests/ui/borrowck/move-error-snippets.stderr
+++ b/tests/ui/borrowck/move-error-snippets.stderr
@@ -9,6 +9,11 @@ LL |         let a = $c;
 LL | sss!();
    | ------ in this macro invocation
    |
+note: if `A` implemented `Clone`, you could clone the value
+  --> $DIR/move-error-snippets.rs:9:1
+   |
+LL | struct A;
+   | ^^^^^^^^
    = note: this error originates in the macro `aaa` which comes from the expansion of the macro `sss` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider borrowing here
    |
diff --git a/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr b/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr
index 6619fb42c28..a4e70b50646 100644
--- a/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr
+++ b/tests/ui/borrowck/move-in-static-initializer-issue-38520.stderr
@@ -3,12 +3,24 @@ error[E0507]: cannot move out of a shared reference
    |
 LL | static Y: usize = get(*&X);
    |                       ^^^ move occurs because value has type `Foo`, which does not implement the `Copy` trait
+   |
+note: if `Foo` implemented `Clone`, you could clone the value
+  --> $DIR/move-in-static-initializer-issue-38520.rs:5:1
+   |
+LL | struct Foo(usize);
+   | ^^^^^^^^^^
 
 error[E0507]: cannot move out of a shared reference
   --> $DIR/move-in-static-initializer-issue-38520.rs:13:22
    |
 LL | const Z: usize = get(*&X);
    |                      ^^^ move occurs because value has type `Foo`, which does not implement the `Copy` trait
+   |
+note: if `Foo` implemented `Clone`, you could clone the value
+  --> $DIR/move-in-static-initializer-issue-38520.rs:5:1
+   |
+LL | struct Foo(usize);
+   | ^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/box/leak-alloc.stderr b/tests/ui/box/leak-alloc.stderr
index 8b8cea3fe84..53ff5f0107d 100644
--- a/tests/ui/box/leak-alloc.stderr
+++ b/tests/ui/box/leak-alloc.stderr
@@ -11,6 +11,12 @@ LL |     drop(alloc);
 LL |
 LL |     use_value(*theref)
    |               ------- borrow later used here
+   |
+note: if `Alloc` implemented `Clone`, you could clone the value
+  --> $DIR/leak-alloc.rs:8:1
+   |
+LL | struct Alloc {}
+   | ^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/derives/deriving-with-repr-packed.stderr b/tests/ui/derives/deriving-with-repr-packed.stderr
index 151be6901b0..26ac532263f 100644
--- a/tests/ui/derives/deriving-with-repr-packed.stderr
+++ b/tests/ui/derives/deriving-with-repr-packed.stderr
@@ -36,6 +36,11 @@ LL | #[repr(packed)]
 LL | struct X(Y);
    |          ^ move occurs because `self.0` has type `Y`, which does not implement the `Copy` trait
    |
+note: if `Y` implemented `Clone`, you could clone the value
+  --> $DIR/deriving-with-repr-packed.rs:16:1
+   |
+LL | struct Y(usize);
+   | ^^^^^^^^
    = note: `#[derive(Debug)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour
    = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/tests/ui/error-codes/E0504.stderr b/tests/ui/error-codes/E0504.stderr
index c8a48961cb3..900cb706bd9 100644
--- a/tests/ui/error-codes/E0504.stderr
+++ b/tests/ui/error-codes/E0504.stderr
@@ -13,6 +13,12 @@ LL |         println!("child function: {}", fancy_num.num);
 ...
 LL |     println!("main function: {}", fancy_ref.num);
    |                                   ------------- borrow later used here
+   |
+note: if `FancyNum` implemented `Clone`, you could clone the value
+  --> $DIR/E0504.rs:1:1
+   |
+LL | struct FancyNum {
+   | ^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/error-codes/E0505.stderr b/tests/ui/error-codes/E0505.stderr
index 250680d2c1c..ce01298a70d 100644
--- a/tests/ui/error-codes/E0505.stderr
+++ b/tests/ui/error-codes/E0505.stderr
@@ -10,6 +10,12 @@ LL |         eat(x);
    |             ^ move out of `x` occurs here
 LL |         _ref_to_val.use_ref();
    |         ----------- borrow later used here
+   |
+note: if `Value` implemented `Clone`, you could clone the value
+  --> $DIR/E0505.rs:1:1
+   |
+LL | struct Value {}
+   | ^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/error-codes/E0507.stderr b/tests/ui/error-codes/E0507.stderr
index 767fedfccbf..60a4daa9d38 100644
--- a/tests/ui/error-codes/E0507.stderr
+++ b/tests/ui/error-codes/E0507.stderr
@@ -11,6 +11,11 @@ note: `TheDarkKnight::nothing_is_true` takes ownership of the receiver `self`, w
    |
 LL |     fn nothing_is_true(self) {}
    |                        ^^^^
+note: if `TheDarkKnight` implemented `Clone`, you could clone the value
+  --> $DIR/E0507.rs:3:1
+   |
+LL | struct TheDarkKnight;
+   | ^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/error-codes/E0508-fail.stderr b/tests/ui/error-codes/E0508-fail.stderr
index 1153b1d09c7..96d3bcb67a5 100644
--- a/tests/ui/error-codes/E0508-fail.stderr
+++ b/tests/ui/error-codes/E0508-fail.stderr
@@ -7,6 +7,11 @@ LL |     let _value = array[0];
    |                  cannot move out of here
    |                  move occurs because `array[_]` has type `NonCopy`, which does not implement the `Copy` trait
    |
+note: if `NonCopy` implemented `Clone`, you could clone the value
+  --> $DIR/E0508-fail.rs:1:1
+   |
+LL | struct NonCopy;
+   | ^^^^^^^^^^^^^^
 help: consider borrowing here
    |
 LL |     let _value = &array[0];
diff --git a/tests/ui/error-codes/E0508.stderr b/tests/ui/error-codes/E0508.stderr
index 4c864e24144..c1b622e2432 100644
--- a/tests/ui/error-codes/E0508.stderr
+++ b/tests/ui/error-codes/E0508.stderr
@@ -7,6 +7,11 @@ LL |     let _value = array[0];
    |                  cannot move out of here
    |                  move occurs because `array[_]` has type `NonCopy`, which does not implement the `Copy` trait
    |
+note: if `NonCopy` implemented `Clone`, you could clone the value
+  --> $DIR/E0508.rs:1:1
+   |
+LL | struct NonCopy;
+   | ^^^^^^^^^^^^^^
 help: consider borrowing here
    |
 LL |     let _value = &array[0];
diff --git a/tests/ui/error-codes/E0509.stderr b/tests/ui/error-codes/E0509.stderr
index 59843a5491a..75c372d0440 100644
--- a/tests/ui/error-codes/E0509.stderr
+++ b/tests/ui/error-codes/E0509.stderr
@@ -7,6 +7,11 @@ LL |     let fancy_field = drop_struct.fancy;
    |                       cannot move out of here
    |                       move occurs because `drop_struct.fancy` has type `FancyNum`, which does not implement the `Copy` trait
    |
+note: if `FancyNum` implemented `Clone`, you could clone the value
+  --> $DIR/E0509.rs:1:1
+   |
+LL | struct FancyNum {
+   | ^^^^^^^^^^^^^^^
 help: consider borrowing here
    |
 LL |     let fancy_field = &drop_struct.fancy;
diff --git a/tests/ui/issues/issue-17385.stderr b/tests/ui/issues/issue-17385.stderr
index 77aa201b335..988db0fb1fc 100644
--- a/tests/ui/issues/issue-17385.stderr
+++ b/tests/ui/issues/issue-17385.stderr
@@ -7,6 +7,12 @@ LL |     drop(foo);
    |          --- value moved here
 LL |     match foo {
    |     ^^^^^^^^^ value used here after move
+   |
+note: if `X` implemented `Clone`, you could clone the value
+  --> $DIR/issue-17385.rs:1:1
+   |
+LL | struct X(isize);
+   | ^^^^^^^^
 
 error[E0382]: use of moved value: `e`
   --> $DIR/issue-17385.rs:25:11
@@ -17,6 +23,12 @@ LL |     drop(e);
    |          - value moved here
 LL |     match e {
    |           ^ value used here after move
+   |
+note: if `Enum` implemented `Clone`, you could clone the value
+  --> $DIR/issue-17385.rs:3:1
+   |
+LL | enum Enum {
+   | ^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/mir/issue-102389.stderr b/tests/ui/mir/issue-102389.stderr
index 1f04d119b56..838eaffb5a0 100644
--- a/tests/ui/mir/issue-102389.stderr
+++ b/tests/ui/mir/issue-102389.stderr
@@ -3,6 +3,12 @@ error[E0507]: cannot move out of `*inbounds` which is behind a shared reference
    |
 LL |     array[*inbounds as usize]
    |           ^^^^^^^^^ move occurs because `*inbounds` has type `Enum`, which does not implement the `Copy` trait
+   |
+note: if `Enum` implemented `Clone`, you could clone the value
+  --> $DIR/issue-102389.rs:1:1
+   |
+LL | enum Enum { A, B, C }
+   | ^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/moves/issue-72649-uninit-in-loop.rs b/tests/ui/moves/issue-72649-uninit-in-loop.rs
index 56c225bab8c..86f389cb3af 100644
--- a/tests/ui/moves/issue-72649-uninit-in-loop.rs
+++ b/tests/ui/moves/issue-72649-uninit-in-loop.rs
@@ -3,6 +3,10 @@
 // 'value moved in previous iteration of loop' message
 
 struct NonCopy;
+//~^ NOTE if `NonCopy` implemented `Clone`
+//~| NOTE if `NonCopy` implemented `Clone`
+//~| NOTE if `NonCopy` implemented `Clone`
+//~| NOTE if `NonCopy` implemented `Clone`
 
 fn good() {
     loop {
diff --git a/tests/ui/moves/issue-72649-uninit-in-loop.stderr b/tests/ui/moves/issue-72649-uninit-in-loop.stderr
index 7e119fe8cda..fe9fa6c0a07 100644
--- a/tests/ui/moves/issue-72649-uninit-in-loop.stderr
+++ b/tests/ui/moves/issue-72649-uninit-in-loop.stderr
@@ -1,5 +1,5 @@
 error[E0382]: use of moved value: `value`
-  --> $DIR/issue-72649-uninit-in-loop.rs:20:22
+  --> $DIR/issue-72649-uninit-in-loop.rs:24:22
    |
 LL |         let value = NonCopy{};
    |             ----- move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait
@@ -9,9 +9,15 @@ LL |         let _used = value;
 LL |
 LL |         let _used2 = value;
    |                      ^^^^^ value used here after move
+   |
+note: if `NonCopy` implemented `Clone`, you could clone the value
+  --> $DIR/issue-72649-uninit-in-loop.rs:5:1
+   |
+LL | struct NonCopy;
+   | ^^^^^^^^^^^^^^
 
 error[E0382]: use of moved value: `value`
-  --> $DIR/issue-72649-uninit-in-loop.rs:32:26
+  --> $DIR/issue-72649-uninit-in-loop.rs:36:26
    |
 LL |     let value = NonCopy{};
    |         ----- move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait
@@ -23,9 +29,15 @@ LL |         let _used = value;
 ...
 LL |             let _used2 = value;
    |                          ^^^^^ value used here after move
+   |
+note: if `NonCopy` implemented `Clone`, you could clone the value
+  --> $DIR/issue-72649-uninit-in-loop.rs:5:1
+   |
+LL | struct NonCopy;
+   | ^^^^^^^^^^^^^^
 
 error[E0382]: use of moved value: `value`
-  --> $DIR/issue-72649-uninit-in-loop.rs:42:21
+  --> $DIR/issue-72649-uninit-in-loop.rs:46:21
    |
 LL |     let value = NonCopy{};
    |         ----- move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait
@@ -34,9 +46,15 @@ LL |     loop {
    |     ---- inside of this loop
 LL |         let _used = value;
    |                     ^^^^^ value moved here, in previous iteration of loop
+   |
+note: if `NonCopy` implemented `Clone`, you could clone the value
+  --> $DIR/issue-72649-uninit-in-loop.rs:5:1
+   |
+LL | struct NonCopy;
+   | ^^^^^^^^^^^^^^
 
 error[E0382]: use of moved value: `value`
-  --> $DIR/issue-72649-uninit-in-loop.rs:53:22
+  --> $DIR/issue-72649-uninit-in-loop.rs:57:22
    |
 LL |     let mut value = NonCopy{};
    |         --------- move occurs because `value` has type `NonCopy`, which does not implement the `Copy` trait
@@ -45,9 +63,15 @@ LL |     loop {
    |     ---- inside of this loop
 LL |         let _used2 = value;
    |                      ^^^^^ value moved here, in previous iteration of loop
+   |
+note: if `NonCopy` implemented `Clone`, you could clone the value
+  --> $DIR/issue-72649-uninit-in-loop.rs:5:1
+   |
+LL | struct NonCopy;
+   | ^^^^^^^^^^^^^^
 
 error[E0381]: used binding `value` isn't initialized
-  --> $DIR/issue-72649-uninit-in-loop.rs:61:21
+  --> $DIR/issue-72649-uninit-in-loop.rs:65:21
    |
 LL |         let value: NonCopy;
    |             ----- binding declared here but left uninitialized
@@ -60,7 +84,7 @@ LL |         let value: NonCopy = todo!();
    |                            +++++++++
 
 error[E0381]: used binding `value` isn't initialized
-  --> $DIR/issue-72649-uninit-in-loop.rs:69:21
+  --> $DIR/issue-72649-uninit-in-loop.rs:73:21
    |
 LL |     let mut value: NonCopy;
    |         --------- binding declared here but left uninitialized
diff --git a/tests/ui/moves/move-fn-self-receiver.stderr b/tests/ui/moves/move-fn-self-receiver.stderr
index 17f48f5f7bf..e6bf52276ac 100644
--- a/tests/ui/moves/move-fn-self-receiver.stderr
+++ b/tests/ui/moves/move-fn-self-receiver.stderr
@@ -101,6 +101,12 @@ LL |     mut_foo;
    |     ^^^^^^^ move out of `mut_foo` occurs here
 LL |     ret;
    |     --- borrow later used here
+   |
+note: if `Foo` implemented `Clone`, you could clone the value
+  --> $DIR/move-fn-self-receiver.rs:5:1
+   |
+LL | struct Foo;
+   | ^^^^^^^^^^
 
 error[E0382]: use of moved value: `rc_foo`
   --> $DIR/move-fn-self-receiver.rs:55:5
@@ -132,6 +138,11 @@ LL |     foo_add + Foo;
 LL |     foo_add;
    |     ^^^^^^^ value used here after move
    |
+note: if `Foo` implemented `Clone`, you could clone the value
+  --> $DIR/move-fn-self-receiver.rs:5:1
+   |
+LL | struct Foo;
+   | ^^^^^^^^^^
 note: calling this operator moves the left-hand side
   --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
 
diff --git a/tests/ui/moves/move-out-of-array-1.stderr b/tests/ui/moves/move-out-of-array-1.stderr
index aa0251dbd85..9e4a08e0cef 100644
--- a/tests/ui/moves/move-out-of-array-1.stderr
+++ b/tests/ui/moves/move-out-of-array-1.stderr
@@ -6,6 +6,12 @@ LL |     a[i]
    |     |
    |     cannot move out of here
    |     move occurs because `a[_]` has type `D`, which does not implement the `Copy` trait
+   |
+note: if `D` implemented `Clone`, you could clone the value
+  --> $DIR/move-out-of-array-1.rs:5:1
+   |
+LL | struct D { _x: u8 }
+   | ^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/nll/issue-21232-partial-init-and-use.stderr b/tests/ui/nll/issue-21232-partial-init-and-use.stderr
index 97ed414b1ec..2aff375f0a7 100644
--- a/tests/ui/nll/issue-21232-partial-init-and-use.stderr
+++ b/tests/ui/nll/issue-21232-partial-init-and-use.stderr
@@ -27,6 +27,12 @@ LL |     let mut s: S<B> = S::new(); drop(s);
    |         move occurs because `s` has type `S<Box<u32>>`, which does not implement the `Copy` trait
 LL |     s.x = 10; s.y = Box::new(20);
    |     ^^^^^^^^ value partially assigned here after move
+   |
+note: if `S<Box<u32>>` implemented `Clone`, you could clone the value
+  --> $DIR/issue-21232-partial-init-and-use.rs:15:1
+   |
+LL | struct S<Y> {
+   | ^^^^^^^^^^^
 
 error[E0382]: assign to part of moved value: `t`
   --> $DIR/issue-21232-partial-init-and-use.rs:116:5
@@ -72,6 +78,12 @@ LL |     let mut s: S<B> = S::new(); drop(s);
    |         move occurs because `s` has type `S<Box<u32>>`, which does not implement the `Copy` trait
 LL |     s.x = 10;
    |     ^^^^^^^^ value partially assigned here after move
+   |
+note: if `S<Box<u32>>` implemented `Clone`, you could clone the value
+  --> $DIR/issue-21232-partial-init-and-use.rs:15:1
+   |
+LL | struct S<Y> {
+   | ^^^^^^^^^^^
 
 error[E0382]: assign to part of moved value: `t`
   --> $DIR/issue-21232-partial-init-and-use.rs:142:5
diff --git a/tests/ui/nll/move-errors.stderr b/tests/ui/nll/move-errors.stderr
index 0d994ef29ba..842ecaf524b 100644
--- a/tests/ui/nll/move-errors.stderr
+++ b/tests/ui/nll/move-errors.stderr
@@ -4,6 +4,11 @@ error[E0507]: cannot move out of `*a` which is behind a shared reference
 LL |     let b = *a;
    |             ^^ move occurs because `*a` has type `A`, which does not implement the `Copy` trait
    |
+note: if `A` implemented `Clone`, you could clone the value
+  --> $DIR/move-errors.rs:1:1
+   |
+LL | struct A(String);
+   | ^^^^^^^^
 help: consider removing the dereference here
    |
 LL -     let b = *a;
@@ -19,6 +24,11 @@ LL |     let b = a[0];
    |             cannot move out of here
    |             move occurs because `a[_]` has type `A`, which does not implement the `Copy` trait
    |
+note: if `A` implemented `Clone`, you could clone the value
+  --> $DIR/move-errors.rs:1:1
+   |
+LL | struct A(String);
+   | ^^^^^^^^
 help: consider borrowing here
    |
 LL |     let b = &a[0];
@@ -30,6 +40,11 @@ error[E0507]: cannot move out of `**r` which is behind a shared reference
 LL |     let s = **r;
    |             ^^^ move occurs because `**r` has type `A`, which does not implement the `Copy` trait
    |
+note: if `A` implemented `Clone`, you could clone the value
+  --> $DIR/move-errors.rs:1:1
+   |
+LL | struct A(String);
+   | ^^^^^^^^
 help: consider removing the dereference here
    |
 LL -     let s = **r;
@@ -42,6 +57,11 @@ error[E0507]: cannot move out of an `Rc`
 LL |     let s = *r;
    |             ^^ move occurs because value has type `A`, which does not implement the `Copy` trait
    |
+note: if `A` implemented `Clone`, you could clone the value
+  --> $DIR/move-errors.rs:1:1
+   |
+LL | struct A(String);
+   | ^^^^^^^^
 help: consider removing the dereference here
    |
 LL -     let s = *r;
@@ -57,6 +77,11 @@ LL |     let a = [A("".to_string())][0];
    |             cannot move out of here
    |             move occurs because value has type `A`, which does not implement the `Copy` trait
    |
+note: if `A` implemented `Clone`, you could clone the value
+  --> $DIR/move-errors.rs:1:1
+   |
+LL | struct A(String);
+   | ^^^^^^^^
 help: consider borrowing here
    |
 LL |     let a = &[A("".to_string())][0];
@@ -96,6 +121,12 @@ error[E0507]: cannot move out of `*a` which is behind a shared reference
    |
 LL |     b = *a;
    |         ^^ move occurs because `*a` has type `A`, which does not implement the `Copy` trait
+   |
+note: if `A` implemented `Clone`, you could clone the value
+  --> $DIR/move-errors.rs:1:1
+   |
+LL | struct A(String);
+   | ^^^^^^^^
 
 error[E0508]: cannot move out of type `[B; 1]`, a non-copy array
   --> $DIR/move-errors.rs:74:11
diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
index 9359244c6eb..00964cb8336 100644
--- a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
+++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
@@ -333,6 +333,11 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
    |                                                                  ^ move occurs because `b` has type `&mut U`, which does not implement the `Copy` trait
    |
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
+note: if `U` implemented `Clone`, you could clone the value
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:17:5
+   |
+LL |     struct U;
+   |     ^^^^^^^^
 
 error[E0507]: cannot move out of `b` in pattern guard
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:66
@@ -341,6 +346,11 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
    |                                                                  ^ move occurs because `b` has type `&mut U`, which does not implement the `Copy` trait
    |
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
+note: if `U` implemented `Clone`, you could clone the value
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:17:5
+   |
+LL |     struct U;
+   |     ^^^^^^^^
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0507]: cannot move out of `a` in pattern guard
diff --git a/tests/ui/union/union-borrow-move-parent-sibling.stderr b/tests/ui/union/union-borrow-move-parent-sibling.stderr
index c9a440a66cc..782fa63280e 100644
--- a/tests/ui/union/union-borrow-move-parent-sibling.stderr
+++ b/tests/ui/union/union-borrow-move-parent-sibling.stderr
@@ -50,6 +50,11 @@ error[E0507]: cannot move out of dereference of `ManuallyDrop<((MockVec<u8>, Moc
 LL |     let a = (u.x.0).0;
    |             ^^^^^^^^^ move occurs because value has type `MockVec<u8>`, which does not implement the `Copy` trait
    |
+note: if `MockVec<u8>` implemented `Clone`, you could clone the value
+  --> $DIR/union-borrow-move-parent-sibling.rs:25:1
+   |
+LL | struct MockVec<T> {
+   | ^^^^^^^^^^^^^^^^^
 help: consider borrowing here
    |
 LL |     let a = &(u.x.0).0;
diff --git a/tests/ui/union/union-move.stderr b/tests/ui/union/union-move.stderr
index 7d13094fbed..5ebb2716e5a 100644
--- a/tests/ui/union/union-move.stderr
+++ b/tests/ui/union/union-move.stderr
@@ -16,6 +16,11 @@ LL | fn move_out<T>(x: T) {}
    |    --------       ^ this parameter takes ownership of the value
    |    |
    |    in this function
+note: if `U1` implemented `Clone`, you could clone the value
+  --> $DIR/union-move.rs:9:1
+   |
+LL | union U1 {
+   | ^^^^^^^^
 
 error[E0382]: use of moved value: `x`
   --> $DIR/union-move.rs:42:18
@@ -35,6 +40,11 @@ LL | fn move_out<T>(x: T) {}
    |    --------       ^ this parameter takes ownership of the value
    |    |
    |    in this function
+note: if `U1` implemented `Clone`, you could clone the value
+  --> $DIR/union-move.rs:9:1
+   |
+LL | union U1 {
+   | ^^^^^^^^
 
 error[E0509]: cannot move out of type `U2`, which implements the `Drop` trait
   --> $DIR/union-move.rs:49:18
diff --git a/tests/ui/variance/variance-issue-20533.stderr b/tests/ui/variance/variance-issue-20533.stderr
index 7060144c776..4515d313ec0 100644
--- a/tests/ui/variance/variance-issue-20533.stderr
+++ b/tests/ui/variance/variance-issue-20533.stderr
@@ -9,6 +9,12 @@ LL |         drop(a);
    |              ^ move out of `a` occurs here
 LL |         drop(x);
    |              - borrow later used here
+   |
+note: if `AffineU32` implemented `Clone`, you could clone the value
+  --> $DIR/variance-issue-20533.rs:26:1
+   |
+LL | struct AffineU32(u32);
+   | ^^^^^^^^^^^^^^^^
 
 error[E0505]: cannot move out of `a` because it is borrowed
   --> $DIR/variance-issue-20533.rs:41:14
@@ -21,6 +27,12 @@ LL |         drop(a);
    |              ^ move out of `a` occurs here
 LL |         drop(x);
    |              - borrow later used here
+   |
+note: if `AffineU32` implemented `Clone`, you could clone the value
+  --> $DIR/variance-issue-20533.rs:26:1
+   |
+LL | struct AffineU32(u32);
+   | ^^^^^^^^^^^^^^^^
 
 error[E0505]: cannot move out of `a` because it is borrowed
   --> $DIR/variance-issue-20533.rs:47:14
@@ -33,6 +45,12 @@ LL |         drop(a);
    |              ^ move out of `a` occurs here
 LL |         drop(x);
    |              - borrow later used here
+   |
+note: if `AffineU32` implemented `Clone`, you could clone the value
+  --> $DIR/variance-issue-20533.rs:26:1
+   |
+LL | struct AffineU32(u32);
+   | ^^^^^^^^^^^^^^^^
 
 error[E0505]: cannot move out of `a` because it is borrowed
   --> $DIR/variance-issue-20533.rs:53:14