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`, 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 = as Clone>::clone(&Rc::new(vec![1, 2])).into_iter(); + let _x = 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 = 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`, 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; - ::clone(&(*foo)).foo(); //~ ERROR cannot move out + ::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 | ::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) where F : Fn() { fn main() { let y = vec![format!("World")]; call(|| { - as Clone>::clone(&y).into_iter(); + 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 | 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`, 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`, 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`, 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`, 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); -impl Deref for S { - type Target = Vec; - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl S { - fn foo(&self) { - // `self.clone()` returns `&S`, not `Vec` - for _ in 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); 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 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; - ::clone(&foo).foo(); //~ ERROR cannot move out + ::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 | ::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`, 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`, 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`, 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`, 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`, 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`, 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`, 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`'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`'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 as Clone>::clone(&selection.1).unwrap().contains(selection.0) { + if 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 as Clone>::clone(&selection.1).unwrap().contains(selection.0) { + if 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 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 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`, 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`, 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`, 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`, 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>`, 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