about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/move_errors.rs10
-rw-r--r--tests/ui/borrowck/borrowck-fn-in-const-a.stderr6
-rw-r--r--tests/ui/borrowck/borrowck-in-static.stderr5
-rw-r--r--tests/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.fixed2
-rw-r--r--tests/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.stderr4
-rw-r--r--tests/ui/borrowck/borrowck-struct-update-with-dtor.stderr5
-rw-r--r--tests/ui/borrowck/clone-span-on-try-operator.fixed2
-rw-r--r--tests/ui/borrowck/clone-span-on-try-operator.stderr5
-rw-r--r--tests/ui/borrowck/issue-64453.stderr5
-rw-r--r--tests/ui/borrowck/move-error-in-promoted.stderr5
-rw-r--r--tests/ui/borrowck/move-from-union-field-issue-66500.stderr24
-rw-r--r--tests/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.fixed2
-rw-r--r--tests/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr4
-rw-r--r--tests/ui/derives/deriving-with-repr-packed-move-errors.stderr96
-rw-r--r--tests/ui/functional-struct-update/functional-struct-update-noncopyable.stderr5
-rw-r--r--tests/ui/issues/issue-2590.stderr5
-rw-r--r--tests/ui/issues/issue-52262.stderr6
-rw-r--r--tests/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr5
-rw-r--r--tests/ui/moves/needs-clone-through-deref.fixed18
-rw-r--r--tests/ui/moves/needs-clone-through-deref.rs1
-rw-r--r--tests/ui/moves/needs-clone-through-deref.stderr6
-rw-r--r--tests/ui/moves/suggest-clone.fixed2
-rw-r--r--tests/ui/moves/suggest-clone.stderr4
-rw-r--r--tests/ui/nll/issue-52086.stderr10
-rw-r--r--tests/ui/nll/issue-52663-span-decl-captured-variable.stderr5
-rw-r--r--tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr8
-rw-r--r--tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr8
-rw-r--r--tests/ui/span/borrowck-call-is-borrow-issue-12224.stderr5
-rw-r--r--tests/ui/suggestions/for-i-in-vec.fixed6
-rw-r--r--tests/ui/suggestions/for-i-in-vec.stderr13
-rw-r--r--tests/ui/suggestions/option-content-move.fixed4
-rw-r--r--tests/ui/suggestions/option-content-move.stderr8
-rw-r--r--tests/ui/trivial-bounds/trivial-bounds-leak-copy.stderr6
-rw-r--r--tests/ui/unboxed-closures/unboxed-closure-illegal-move.stderr20
-rw-r--r--tests/ui/union/union-move.stderr5
35 files changed, 296 insertions, 29 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
index 0d1b875cbed..3a1fbab452e 100644
--- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs
@@ -474,6 +474,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     Some(desc) => format!("`{desc}`"),
                     None => "value".to_string(),
                 };
+
+                if let Some(expr) = self.find_expr(span) {
+                    self.suggest_cloning(err, place_ty, expr, span);
+                }
+
                 err.subdiagnostic(
                     self.dcx(),
                     crate::session_diagnostics::TypeNoCopy::Label {
@@ -582,6 +587,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
 
             if binds_to.len() == 1 {
                 let place_desc = &format!("`{}`", self.local_names[*local].unwrap());
+
+                if let Some(expr) = self.find_expr(binding_span) {
+                    self.suggest_cloning(err, bind_to.ty, expr, binding_span);
+                }
+
                 err.subdiagnostic(
                     self.dcx(),
                     crate::session_diagnostics::TypeNoCopy::Label {
diff --git a/tests/ui/borrowck/borrowck-fn-in-const-a.stderr b/tests/ui/borrowck/borrowck-fn-in-const-a.stderr
index e05696864fd..7bf0f859fdd 100644
--- a/tests/ui/borrowck/borrowck-fn-in-const-a.stderr
+++ b/tests/ui/borrowck/borrowck-fn-in-const-a.stderr
@@ -3,6 +3,12 @@ error[E0507]: cannot move out of `*x` which is behind a shared reference
    |
 LL |         return *x
    |                ^^ move occurs because `*x` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL -         return *x
+LL +         return x.clone()
+   |
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/borrowck/borrowck-in-static.stderr b/tests/ui/borrowck/borrowck-in-static.stderr
index 8171e6950ac..745b02ae21b 100644
--- a/tests/ui/borrowck/borrowck-in-static.stderr
+++ b/tests/ui/borrowck/borrowck-in-static.stderr
@@ -7,6 +7,11 @@ LL |     Box::new(|| x)
    |              -- ^ move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
    |              |
    |              captured by this `Fn` closure
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     Box::new(|| x.clone())
+   |                  ++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.fixed b/tests/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.fixed
index 8d5ebbc7744..a19db7e5cd3 100644
--- a/tests/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.fixed
+++ b/tests/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.fixed
@@ -2,6 +2,6 @@
 use std::rc::Rc;
 
 pub fn main() {
-    let _x = <Vec<i32> as Clone>::clone(&Rc::new(vec![1, 2])).into_iter();
+    let _x = <Vec<i32> as Clone>::clone(&Rc::new(vec![1, 2]).clone()).into_iter();
     //~^ ERROR [E0507]
 }
diff --git a/tests/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.stderr b/tests/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.stderr
index 076f0ce3440..577c2de38be 100644
--- a/tests/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.stderr
+++ b/tests/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.stderr
@@ -12,6 +12,10 @@ help: you can `clone` the value and consume it, but this might not be your desir
    |
 LL |     let _x = <Vec<i32> as Clone>::clone(&Rc::new(vec![1, 2])).into_iter();
    |              ++++++++++++++++++++++++++++                   +
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     let _x = Rc::new(vec![1, 2]).clone().into_iter();
+   |                                 ++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/borrowck/borrowck-struct-update-with-dtor.stderr b/tests/ui/borrowck/borrowck-struct-update-with-dtor.stderr
index af32f279100..01004fa56c6 100644
--- a/tests/ui/borrowck/borrowck-struct-update-with-dtor.stderr
+++ b/tests/ui/borrowck/borrowck-struct-update-with-dtor.stderr
@@ -15,6 +15,11 @@ LL |     let _s2 = T{a: 2, ..s0};
    |               |
    |               cannot move out of here
    |               move occurs because `s0.mv` has type `Box<isize>`, which does not implement the `Copy` trait
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     let _s2 = T{a: 2, ..s0}.clone();
+   |                            ++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/borrowck/clone-span-on-try-operator.fixed b/tests/ui/borrowck/clone-span-on-try-operator.fixed
index 59253c98079..59a162e72c1 100644
--- a/tests/ui/borrowck/clone-span-on-try-operator.fixed
+++ b/tests/ui/borrowck/clone-span-on-try-operator.fixed
@@ -7,5 +7,5 @@ impl Foo {
 }
 fn main() {
     let foo = &Foo;
-    <Foo as Clone>::clone(&(*foo)).foo(); //~ ERROR cannot move out
+    <Foo as Clone>::clone(&foo.clone()).foo(); //~ ERROR cannot move out
 }
diff --git a/tests/ui/borrowck/clone-span-on-try-operator.stderr b/tests/ui/borrowck/clone-span-on-try-operator.stderr
index adf84e49a9f..c2c63f94943 100644
--- a/tests/ui/borrowck/clone-span-on-try-operator.stderr
+++ b/tests/ui/borrowck/clone-span-on-try-operator.stderr
@@ -15,6 +15,11 @@ help: you can `clone` the value and consume it, but this might not be your desir
    |
 LL |     <Foo as Clone>::clone(&(*foo)).foo();
    |     +++++++++++++++++++++++      +
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL -     (*foo).foo();
+LL +     foo.clone().foo();
+   |
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/borrowck/issue-64453.stderr b/tests/ui/borrowck/issue-64453.stderr
index f032ea779dd..0e4a8d42f6e 100644
--- a/tests/ui/borrowck/issue-64453.stderr
+++ b/tests/ui/borrowck/issue-64453.stderr
@@ -22,6 +22,11 @@ error[E0507]: cannot move out of static item `settings_dir`
    |
 LL |     let settings_data = from_string(settings_dir);
    |                                     ^^^^^^^^^^^^ move occurs because `settings_dir` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     let settings_data = from_string(settings_dir.clone());
+   |                                                 ++++++++
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/borrowck/move-error-in-promoted.stderr b/tests/ui/borrowck/move-error-in-promoted.stderr
index 03c0297c5a9..8d42df24e27 100644
--- a/tests/ui/borrowck/move-error-in-promoted.stderr
+++ b/tests/ui/borrowck/move-error-in-promoted.stderr
@@ -6,6 +6,11 @@ LL |     let _ = S1(C[0]).clone();
    |                |
    |                cannot move out of here
    |                move occurs because value has type `S2`, which does not implement the `Copy` trait
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     let _ = S1(C[0].clone()).clone();
+   |                    ++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/borrowck/move-from-union-field-issue-66500.stderr b/tests/ui/borrowck/move-from-union-field-issue-66500.stderr
index 70078582713..c951ce8e3cd 100644
--- a/tests/ui/borrowck/move-from-union-field-issue-66500.stderr
+++ b/tests/ui/borrowck/move-from-union-field-issue-66500.stderr
@@ -3,24 +3,48 @@ error[E0507]: cannot move out of `*u.a` which is behind a shared reference
    |
 LL |     *u.a
    |     ^^^^ move occurs because `*u.a` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL -     *u.a
+LL +     u.a.clone()
+   |
 
 error[E0507]: cannot move out of `*u.b` which is behind a mutable reference
   --> $DIR/move-from-union-field-issue-66500.rs:16:5
    |
 LL |     *u.b
    |     ^^^^ move occurs because `*u.b` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL -     *u.b
+LL +     u.b.clone()
+   |
 
 error[E0507]: cannot move out of `*u.c` which is behind a raw pointer
   --> $DIR/move-from-union-field-issue-66500.rs:20:5
    |
 LL |     *u.c
    |     ^^^^ move occurs because `*u.c` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL -     *u.c
+LL +     u.c.clone()
+   |
 
 error[E0507]: cannot move out of `*u.d` which is behind a raw pointer
   --> $DIR/move-from-union-field-issue-66500.rs:24:5
    |
 LL |     *u.d
    |     ^^^^ move occurs because `*u.d` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL -     *u.d
+LL +     u.d.clone()
+   |
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.fixed b/tests/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.fixed
index 8add3a5f2b6..3b4f7c8465c 100644
--- a/tests/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.fixed
+++ b/tests/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.fixed
@@ -9,7 +9,7 @@ fn call<F>(f: F) where F : Fn() {
 fn main() {
     let y = vec![format!("World")];
     call(|| {
-        <Vec<String> as Clone>::clone(&y).into_iter();
+        <Vec<String> as Clone>::clone(&y.clone()).into_iter();
         //~^ ERROR cannot move out of `y`, a captured variable in an `Fn` closure
     });
 }
diff --git a/tests/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr b/tests/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr
index a2ff70255f5..177e9c8d248 100644
--- a/tests/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr
+++ b/tests/ui/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.stderr
@@ -16,6 +16,10 @@ help: you can `clone` the value and consume it, but this might not be your desir
    |
 LL |         <Vec<String> as Clone>::clone(&y).into_iter();
    |         +++++++++++++++++++++++++++++++ +
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         y.clone().into_iter();
+   |          ++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/derives/deriving-with-repr-packed-move-errors.stderr b/tests/ui/derives/deriving-with-repr-packed-move-errors.stderr
index c538061b365..2de4ee4eabd 100644
--- a/tests/ui/derives/deriving-with-repr-packed-move-errors.stderr
+++ b/tests/ui/derives/deriving-with-repr-packed-move-errors.stderr
@@ -8,6 +8,10 @@ LL | struct StructA(String);
    |
    = 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)
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL | struct StructA(String.clone());
+   |                      ++++++++
 
 error[E0507]: cannot move out of `self` which is behind a shared reference
   --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16
@@ -19,6 +23,10 @@ LL | struct StructA(String);
    |
    = note: `#[derive(PartialEq)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour
    = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL | struct StructA(String.clone());
+   |                      ++++++++
 
 error[E0507]: cannot move out of `other` which is behind a shared reference
   --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16
@@ -30,6 +38,10 @@ LL | struct StructA(String);
    |
    = note: `#[derive(PartialEq)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour
    = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL | struct StructA(String.clone());
+   |                      ++++++++
 
 error[E0507]: cannot move out of `self` which is behind a shared reference
   --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16
@@ -41,6 +53,10 @@ LL | struct StructA(String);
    |
    = note: `#[derive(PartialOrd)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour
    = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL | struct StructA(String.clone());
+   |                      ++++++++
 
 error[E0507]: cannot move out of `other` which is behind a shared reference
   --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16
@@ -52,6 +68,10 @@ LL | struct StructA(String);
    |
    = note: `#[derive(PartialOrd)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour
    = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL | struct StructA(String.clone());
+   |                      ++++++++
 
 error[E0507]: cannot move out of `self` which is behind a shared reference
   --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16
@@ -63,6 +83,10 @@ LL | struct StructA(String);
    |
    = note: `#[derive(Ord)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour
    = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL | struct StructA(String.clone());
+   |                      ++++++++
 
 error[E0507]: cannot move out of `other` which is behind a shared reference
   --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16
@@ -74,6 +98,10 @@ LL | struct StructA(String);
    |
    = note: `#[derive(Ord)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour
    = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL | struct StructA(String.clone());
+   |                      ++++++++
 
 error[E0507]: cannot move out of `self` which is behind a shared reference
   --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16
@@ -85,6 +113,10 @@ LL | struct StructA(String);
    |
    = note: `#[derive(Hash)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour
    = note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL | struct StructA(String.clone());
+   |                      ++++++++
 
 error[E0507]: cannot move out of `self` which is behind a shared reference
   --> $DIR/deriving-with-repr-packed-move-errors.rs:13:16
@@ -96,78 +128,142 @@ LL | struct StructA(String);
    |
    = note: `#[derive(Clone)]` triggers a move because taking references to the fields of a packed struct is undefined behaviour
    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL | struct StructA(String.clone());
+   |                      ++++++++
 
 error[E0507]: cannot move out of `self` which is behind a shared reference
   --> $DIR/deriving-with-repr-packed-move-errors.rs:28:9
    |
 LL |         self.0
    |         ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         self.0.clone()
+   |               ++++++++
 
 error[E0507]: cannot move out of `self` which is behind a shared reference
   --> $DIR/deriving-with-repr-packed-move-errors.rs:38:20
    |
 LL |         let x = &{ self.0 };
    |                    ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         let x = &{ self.0.clone() };
+   |                          ++++++++
 
 error[E0507]: cannot move out of `self` which is behind a shared reference
   --> $DIR/deriving-with-repr-packed-move-errors.rs:45:12
    |
 LL |         ({ self.0 }) == ({ other.0 })
    |            ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         ({ self.0.clone() }) == ({ other.0 })
+   |                  ++++++++
 
 error[E0507]: cannot move out of `other` which is behind a shared reference
   --> $DIR/deriving-with-repr-packed-move-errors.rs:45:28
    |
 LL |         ({ self.0 }) == ({ other.0 })
    |                            ^^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         ({ self.0 }) == ({ other.0.clone() })
+   |                                   ++++++++
 
 error[E0507]: cannot move out of `self` which is behind a shared reference
   --> $DIR/deriving-with-repr-packed-move-errors.rs:53:36
    |
 LL |         PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 })
    |                                    ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         PartialOrd::partial_cmp(&{ self.0.clone() }, &{ other.0 })
+   |                                          ++++++++
 
 error[E0507]: cannot move out of `other` which is behind a shared reference
   --> $DIR/deriving-with-repr-packed-move-errors.rs:53:49
    |
 LL |         PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 })
    |                                                 ^^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         PartialOrd::partial_cmp(&{ self.0 }, &{ other.0.clone() })
+   |                                                        ++++++++
 
 error[E0507]: cannot move out of `self` which is behind a shared reference
   --> $DIR/deriving-with-repr-packed-move-errors.rs:68:20
    |
 LL |         let x = &{ self.0 };
    |                    ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         let x = &{ self.0.clone() };
+   |                          ++++++++
 
 error[E0507]: cannot move out of `self` which is behind a shared reference
   --> $DIR/deriving-with-repr-packed-move-errors.rs:75:12
    |
 LL |         ({ self.0 }) == ({ other.0 })
    |            ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         ({ self.0.clone() }) == ({ other.0 })
+   |                  ++++++++
 
 error[E0507]: cannot move out of `other` which is behind a shared reference
   --> $DIR/deriving-with-repr-packed-move-errors.rs:75:28
    |
 LL |         ({ self.0 }) == ({ other.0 })
    |                            ^^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         ({ self.0 }) == ({ other.0.clone() })
+   |                                   ++++++++
 
 error[E0507]: cannot move out of `self` which is behind a shared reference
   --> $DIR/deriving-with-repr-packed-move-errors.rs:83:36
    |
 LL |         PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 })
    |                                    ^^^^^^ move occurs because `self.0` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         PartialOrd::partial_cmp(&{ self.0.clone() }, &{ other.0 })
+   |                                          ++++++++
 
 error[E0507]: cannot move out of `other` which is behind a shared reference
   --> $DIR/deriving-with-repr-packed-move-errors.rs:83:49
    |
 LL |         PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 })
    |                                                 ^^^^^^^ move occurs because `other.0` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         PartialOrd::partial_cmp(&{ self.0 }, &{ other.0.clone() })
+   |                                                        ++++++++
 
 error[E0507]: cannot move out of `arg` which is behind a shared reference
   --> $DIR/deriving-with-repr-packed-move-errors.rs:92:5
    |
 LL |     arg.0
    |     ^^^^^ move occurs because `arg.0` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     arg.0.clone()
+   |          ++++++++
 
 error: aborting due to 21 previous errors
 
diff --git a/tests/ui/functional-struct-update/functional-struct-update-noncopyable.stderr b/tests/ui/functional-struct-update/functional-struct-update-noncopyable.stderr
index 16808f29dac..4d314f4f7c3 100644
--- a/tests/ui/functional-struct-update/functional-struct-update-noncopyable.stderr
+++ b/tests/ui/functional-struct-update/functional-struct-update-noncopyable.stderr
@@ -6,6 +6,11 @@ LL |     let _b = A { y: Arc::new(3), ..a };
    |              |
    |              cannot move out of here
    |              move occurs because `a.x` has type `Arc<isize>`, which does not implement the `Copy` trait
+   |
+help: clone the value to increment its reference count
+   |
+LL |     let _b = A { y: Arc::new(3), ..a }.clone();
+   |                                       ++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/issues/issue-2590.stderr b/tests/ui/issues/issue-2590.stderr
index 517b4814eae..822856652e9 100644
--- a/tests/ui/issues/issue-2590.stderr
+++ b/tests/ui/issues/issue-2590.stderr
@@ -3,6 +3,11 @@ error[E0507]: cannot move out of `self.tokens` which is behind a shared referenc
    |
 LL |         self.tokens
    |         ^^^^^^^^^^^ move occurs because `self.tokens` has type `Vec<isize>`, which does not implement the `Copy` trait
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         self.tokens.clone()
+   |                    ++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/issues/issue-52262.stderr b/tests/ui/issues/issue-52262.stderr
index ce8e6fe2bf8..51959f22b97 100644
--- a/tests/ui/issues/issue-52262.stderr
+++ b/tests/ui/issues/issue-52262.stderr
@@ -3,6 +3,12 @@ error[E0507]: cannot move out of `*key` which is behind a shared reference
    |
 LL |                 String::from_utf8(*key).unwrap()
    |                                   ^^^^ move occurs because `*key` has type `Vec<u8>`, which does not implement the `Copy` trait
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL -                 String::from_utf8(*key).unwrap()
+LL +                 String::from_utf8(key.clone()).unwrap()
+   |
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr b/tests/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr
index 513631b2060..523134a9425 100644
--- a/tests/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr
+++ b/tests/ui/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.stderr
@@ -7,6 +7,11 @@ LL |     let _f = to_fn(|| test(i));
    |                    --      ^ move occurs because `i` has type `Box<usize>`, which does not implement the `Copy` trait
    |                    |
    |                    captured by this `Fn` closure
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     let _f = to_fn(|| test(i.clone()));
+   |                             ++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/moves/needs-clone-through-deref.fixed b/tests/ui/moves/needs-clone-through-deref.fixed
deleted file mode 100644
index 8b201c4720d..00000000000
--- a/tests/ui/moves/needs-clone-through-deref.fixed
+++ /dev/null
@@ -1,18 +0,0 @@
-//@ run-rustfix
-#![allow(dead_code, noop_method_call)]
-use std::ops::Deref;
-struct S(Vec<usize>);
-impl Deref for S {
-    type Target = Vec<usize>;
-    fn deref(&self) -> &Self::Target {
-        &self.0
-    }
-}
-
-impl S {
-    fn foo(&self) {
-        // `self.clone()` returns `&S`, not `Vec`
-        for _ in <Vec<usize> as Clone>::clone(&self).into_iter() {} //~ ERROR cannot move out of dereference of `S`
-    }
-}
-fn main() {}
diff --git a/tests/ui/moves/needs-clone-through-deref.rs b/tests/ui/moves/needs-clone-through-deref.rs
index ca57478ba98..245b7c167fa 100644
--- a/tests/ui/moves/needs-clone-through-deref.rs
+++ b/tests/ui/moves/needs-clone-through-deref.rs
@@ -1,4 +1,3 @@
-//@ run-rustfix
 #![allow(dead_code, noop_method_call)]
 use std::ops::Deref;
 struct S(Vec<usize>);
diff --git a/tests/ui/moves/needs-clone-through-deref.stderr b/tests/ui/moves/needs-clone-through-deref.stderr
index 1f9aefeb4dd..8357ed9ff79 100644
--- a/tests/ui/moves/needs-clone-through-deref.stderr
+++ b/tests/ui/moves/needs-clone-through-deref.stderr
@@ -1,5 +1,5 @@
 error[E0507]: cannot move out of dereference of `S`
-  --> $DIR/needs-clone-through-deref.rs:15:18
+  --> $DIR/needs-clone-through-deref.rs:14:18
    |
 LL |         for _ in self.clone().into_iter() {}
    |                  ^^^^^^^^^^^^ ----------- value moved due to this method call
@@ -12,6 +12,10 @@ help: you can `clone` the value and consume it, but this might not be your desir
    |
 LL |         for _ in <Vec<usize> as Clone>::clone(&self).into_iter() {}
    |                  ++++++++++++++++++++++++++++++    ~
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         for _ in self.clone().clone().into_iter() {}
+   |                              ++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/moves/suggest-clone.fixed b/tests/ui/moves/suggest-clone.fixed
index 59276a7b96d..59a162e72c1 100644
--- a/tests/ui/moves/suggest-clone.fixed
+++ b/tests/ui/moves/suggest-clone.fixed
@@ -7,5 +7,5 @@ impl Foo {
 }
 fn main() {
     let foo = &Foo;
-    <Foo as Clone>::clone(&foo).foo(); //~ ERROR cannot move out
+    <Foo as Clone>::clone(&foo.clone()).foo(); //~ ERROR cannot move out
 }
diff --git a/tests/ui/moves/suggest-clone.stderr b/tests/ui/moves/suggest-clone.stderr
index 25e89a58955..f8e0ccdfcef 100644
--- a/tests/ui/moves/suggest-clone.stderr
+++ b/tests/ui/moves/suggest-clone.stderr
@@ -15,6 +15,10 @@ help: you can `clone` the value and consume it, but this might not be your desir
    |
 LL |     <Foo as Clone>::clone(&foo).foo();
    |     +++++++++++++++++++++++   +
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     foo.clone().foo();
+   |        ++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/nll/issue-52086.stderr b/tests/ui/nll/issue-52086.stderr
index 3b2dae9b72b..e4f0c49e557 100644
--- a/tests/ui/nll/issue-52086.stderr
+++ b/tests/ui/nll/issue-52086.stderr
@@ -3,12 +3,22 @@ error[E0507]: cannot move out of an `Rc`
    |
 LL |     drop(x.field);
    |          ^^^^^^^ move occurs because value has type `Vec<i32>`, which does not implement the `Copy` trait
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     drop(x.field.clone());
+   |                 ++++++++
 
 error[E0507]: cannot move out of an `Arc`
   --> $DIR/issue-52086.rs:12:10
    |
 LL |     drop(y.field);
    |          ^^^^^^^ move occurs because value has type `Vec<i32>`, which does not implement the `Copy` trait
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |     drop(y.field.clone());
+   |                 ++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/nll/issue-52663-span-decl-captured-variable.stderr b/tests/ui/nll/issue-52663-span-decl-captured-variable.stderr
index 587f3071027..fbaec8a6008 100644
--- a/tests/ui/nll/issue-52663-span-decl-captured-variable.stderr
+++ b/tests/ui/nll/issue-52663-span-decl-captured-variable.stderr
@@ -7,6 +7,11 @@ LL |        expect_fn(|| drop(x.0));
    |                  --      ^^^ move occurs because `x.0` has type `Vec<i32>`, which does not implement the `Copy` trait
    |                  |
    |                  captured by this `Fn` closure
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |        expect_fn(|| drop(x.0.clone()));
+   |                             ++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr b/tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr
index a749361bf30..0ab70c5ae8a 100644
--- a/tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr
+++ b/tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr
@@ -5,6 +5,10 @@ LL |         VecWrapper::A(v) if { drop(v); false } => 1,
    |                                    ^ move occurs because `v` has type `Vec<i32>`, which does not implement the `Copy` trait
    |
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         VecWrapper::A(v) if { drop(v.clone()); false } => 1,
+   |                                     ++++++++
 
 error[E0507]: cannot move out of `v` in pattern guard
   --> $DIR/rfc-reject-double-move-across-arms.rs:15:51
@@ -13,6 +17,10 @@ LL |         VecWrapper::A(v) if let Some(()) = { drop(v); None } => 1,
    |                                                   ^ move occurs because `v` has type `Vec<i32>`, which does not implement the `Copy` trait
    |
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         VecWrapper::A(v) if let Some(()) = { drop(v.clone()); None } => 1,
+   |                                                    ++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr b/tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr
index 9285492b224..c261f994283 100644
--- a/tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr
+++ b/tests/ui/rfcs/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr
@@ -5,6 +5,10 @@ LL |         A { a: v } if { drop(v); true } => v,
    |                              ^ move occurs because `v` has type `Box<i32>`, which does not implement the `Copy` trait
    |
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         A { a: v } if { drop(v.clone()); true } => v,
+   |                               ++++++++
 
 error[E0507]: cannot move out of `v` in pattern guard
   --> $DIR/rfc-reject-double-move-in-first-arm.rs:17:45
@@ -13,6 +17,10 @@ LL |         A { a: v } if let Some(()) = { drop(v); Some(()) } => v,
    |                                             ^ move occurs because `v` has type `Box<i32>`, which does not implement the `Copy` trait
    |
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         A { a: v } if let Some(()) = { drop(v.clone()); Some(()) } => v,
+   |                                              ++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/span/borrowck-call-is-borrow-issue-12224.stderr b/tests/ui/span/borrowck-call-is-borrow-issue-12224.stderr
index bac7801f7f4..f37dc320fa3 100644
--- a/tests/ui/span/borrowck-call-is-borrow-issue-12224.stderr
+++ b/tests/ui/span/borrowck-call-is-borrow-issue-12224.stderr
@@ -43,6 +43,11 @@ LL |     f(Box::new(|a| {
 LL |
 LL |         foo(f);
    |             ^ move occurs because `f` has type `{closure@$DIR/borrowck-call-is-borrow-issue-12224.rs:52:17: 52:58}`, which does not implement the `Copy` trait
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         foo(f.clone());
+   |              ++++++++
 
 error[E0505]: cannot move out of `f` because it is borrowed
   --> $DIR/borrowck-call-is-borrow-issue-12224.rs:55:16
diff --git a/tests/ui/suggestions/for-i-in-vec.fixed b/tests/ui/suggestions/for-i-in-vec.fixed
index f266e80bcfa..17ae6fb5ab7 100644
--- a/tests/ui/suggestions/for-i-in-vec.fixed
+++ b/tests/ui/suggestions/for-i-in-vec.fixed
@@ -8,9 +8,9 @@ struct Foo {
 
 impl Foo {
     fn bar(&self) {
-        for _ in &self.v { //~ ERROR cannot move out of `self.v` which is behind a shared reference
+        for _ in &self.v.clone() { //~ ERROR cannot move out of `self.v` which is behind a shared reference
         }
-        for _ in &self.h { //~ ERROR cannot move out of `self.h` which is behind a shared reference
+        for _ in &self.h.clone() { //~ ERROR cannot move out of `self.h` which is behind a shared reference
         }
     }
 }
@@ -18,7 +18,7 @@ impl Foo {
 const LOADERS: &Vec<&'static u8> = &Vec::new();
 
 pub fn break_code() -> Option<&'static u8> {
-    for loader in &*LOADERS { //~ ERROR cannot move out of a shared reference
+    for loader in &LOADERS.clone() { //~ ERROR cannot move out of a shared reference
         return Some(loader);
     }
     None
diff --git a/tests/ui/suggestions/for-i-in-vec.stderr b/tests/ui/suggestions/for-i-in-vec.stderr
index c5b81e6b871..64eb4f8bd23 100644
--- a/tests/ui/suggestions/for-i-in-vec.stderr
+++ b/tests/ui/suggestions/for-i-in-vec.stderr
@@ -13,6 +13,10 @@ help: consider iterating over a slice of the `Vec<u32>`'s content to avoid movin
    |
 LL |         for _ in &self.v {
    |                  +
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         for _ in self.v.clone() {
+   |                        ++++++++
 
 error[E0507]: cannot move out of `self.h` which is behind a shared reference
   --> $DIR/for-i-in-vec.rs:13:18
@@ -27,6 +31,10 @@ help: consider iterating over a slice of the `HashMap<i32, i32>`'s content to av
    |
 LL |         for _ in &self.h {
    |                  +
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         for _ in self.h.clone() {
+   |                        ++++++++
 
 error[E0507]: cannot move out of a shared reference
   --> $DIR/for-i-in-vec.rs:21:19
@@ -43,6 +51,11 @@ help: consider iterating over a slice of the `Vec<&u8>`'s content to avoid movin
    |
 LL |     for loader in &*LOADERS {
    |                   +
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL -     for loader in *LOADERS {
+LL +     for loader in LOADERS.clone() {
+   |
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/suggestions/option-content-move.fixed b/tests/ui/suggestions/option-content-move.fixed
index fbed486cef7..4a5a9483c20 100644
--- a/tests/ui/suggestions/option-content-move.fixed
+++ b/tests/ui/suggestions/option-content-move.fixed
@@ -7,7 +7,7 @@ impl LipogramCorpora {
     pub fn validate_all(&mut self) -> Result<(), char> {
         for selection in &self.selections {
             if selection.1.is_some() {
-                if <Option<String> as Clone>::clone(&selection.1).unwrap().contains(selection.0) {
+                if <Option<String> as Clone>::clone(&selection.1.clone()).unwrap().contains(selection.0) {
                 //~^ ERROR cannot move out of `selection.1`
                     return Err(selection.0);
                 }
@@ -25,7 +25,7 @@ impl LipogramCorpora2 {
     pub fn validate_all(&mut self) -> Result<(), char> {
         for selection in &self.selections {
             if selection.1.is_ok() {
-                if <Result<String, String> as Clone>::clone(&selection.1).unwrap().contains(selection.0) {
+                if <Result<String, String> as Clone>::clone(&selection.1.clone()).unwrap().contains(selection.0) {
                 //~^ ERROR cannot move out of `selection.1`
                     return Err(selection.0);
                 }
diff --git a/tests/ui/suggestions/option-content-move.stderr b/tests/ui/suggestions/option-content-move.stderr
index e5de150275d..a382a04344a 100644
--- a/tests/ui/suggestions/option-content-move.stderr
+++ b/tests/ui/suggestions/option-content-move.stderr
@@ -13,6 +13,10 @@ help: you can `clone` the value and consume it, but this might not be your desir
    |
 LL |                 if <Option<String> as Clone>::clone(&selection.1).unwrap().contains(selection.0) {
    |                    ++++++++++++++++++++++++++++++++++           +
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |                 if selection.1.clone().unwrap().contains(selection.0) {
+   |                               ++++++++
 
 error[E0507]: cannot move out of `selection.1` which is behind a shared reference
   --> $DIR/option-content-move.rs:28:20
@@ -29,6 +33,10 @@ help: you can `clone` the value and consume it, but this might not be your desir
    |
 LL |                 if <Result<String, String> as Clone>::clone(&selection.1).unwrap().contains(selection.0) {
    |                    ++++++++++++++++++++++++++++++++++++++++++           +
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |                 if selection.1.clone().unwrap().contains(selection.0) {
+   |                               ++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/trivial-bounds/trivial-bounds-leak-copy.stderr b/tests/ui/trivial-bounds/trivial-bounds-leak-copy.stderr
index e48d48a7271..4efb883ac74 100644
--- a/tests/ui/trivial-bounds/trivial-bounds-leak-copy.stderr
+++ b/tests/ui/trivial-bounds/trivial-bounds-leak-copy.stderr
@@ -3,6 +3,12 @@ error[E0507]: cannot move out of `*t` which is behind a shared reference
    |
 LL |     *t
    |     ^^ move occurs because `*t` has type `String`, which does not implement the `Copy` trait
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL -     *t
+LL +     t.clone()
+   |
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/unboxed-closures/unboxed-closure-illegal-move.stderr b/tests/ui/unboxed-closures/unboxed-closure-illegal-move.stderr
index bfa3061de08..5b995ff1585 100644
--- a/tests/ui/unboxed-closures/unboxed-closure-illegal-move.stderr
+++ b/tests/ui/unboxed-closures/unboxed-closure-illegal-move.stderr
@@ -7,6 +7,11 @@ LL |         let f = to_fn(|| drop(x));
    |                       --      ^ move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
    |                       |
    |                       captured by this `Fn` closure
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         let f = to_fn(|| drop(x.clone()));
+   |                                ++++++++
 
 error[E0507]: cannot move out of `x`, a captured variable in an `FnMut` closure
   --> $DIR/unboxed-closure-illegal-move.rs:19:35
@@ -17,6 +22,11 @@ LL |         let f = to_fn_mut(|| drop(x));
    |                           --      ^ move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
    |                           |
    |                           captured by this `FnMut` closure
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         let f = to_fn_mut(|| drop(x.clone()));
+   |                                    ++++++++
 
 error[E0507]: cannot move out of `x`, a captured variable in an `Fn` closure
   --> $DIR/unboxed-closure-illegal-move.rs:28:36
@@ -27,6 +37,11 @@ LL |         let f = to_fn(move || drop(x));
    |                       -------      ^ move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
    |                       |
    |                       captured by this `Fn` closure
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         let f = to_fn(move || drop(x.clone()));
+   |                                     ++++++++
 
 error[E0507]: cannot move out of `x`, a captured variable in an `FnMut` closure
   --> $DIR/unboxed-closure-illegal-move.rs:32:40
@@ -37,6 +52,11 @@ LL |         let f = to_fn_mut(move || drop(x));
    |                           -------      ^ move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
    |                           |
    |                           captured by this `FnMut` closure
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         let f = to_fn_mut(move || drop(x.clone()));
+   |                                         ++++++++
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/union/union-move.stderr b/tests/ui/union/union-move.stderr
index 47fb801a50e..7d13094fbed 100644
--- a/tests/ui/union/union-move.stderr
+++ b/tests/ui/union/union-move.stderr
@@ -44,6 +44,11 @@ LL |         move_out(x.f1_nocopy);
    |                  |
    |                  cannot move out of here
    |                  move occurs because `x.f1_nocopy` has type `ManuallyDrop<RefCell<i32>>`, which does not implement the `Copy` trait
+   |
+help: consider cloning the value if the performance cost is acceptable
+   |
+LL |         move_out(x.f1_nocopy.clone());
+   |                             ++++++++
 
 error: aborting due to 3 previous errors