diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index f3dcd594588..862ae091604 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -460,7 +460,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } fn add_move_error_suggestions(&self, err: &mut Diagnostic, binds_to: &[Local]) { - let mut suggestions: Vec<(Span, &str, String)> = Vec::new(); + let mut suggestions: Vec<(Span, String, String)> = Vec::new(); for local in binds_to { let bind_to = &self.body.local_decls[*local]; if let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var( @@ -469,7 +469,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { { let Ok(pat_snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(pat_span) else { continue; }; - let Some(stripped) = pat_snippet.strip_prefix('&') else { continue; }; + let Some(stripped) = pat_snippet.strip_prefix('&') else { + suggestions.push(( + bind_to.source_info.span.shrink_to_lo(), + "consider borrowing the pattern binding".to_string(), + "ref ".to_string(), + )); + continue; + }; let inner_pat_snippet = stripped.trim_start(); let (pat_span, suggestion, to_remove) = if inner_pat_snippet.starts_with("mut") && inner_pat_snippet["mut".len()..].starts_with(rustc_lexer::is_whitespace) @@ -488,18 +495,17 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { ); (pat_span, String::new(), "borrow") }; - suggestions.push((pat_span, to_remove, suggestion.to_owned())); + suggestions.push(( + pat_span, + format!("consider removing the {to_remove}"), + suggestion.to_string(), + )); } } suggestions.sort_unstable_by_key(|&(span, _, _)| span); suggestions.dedup_by_key(|&mut (span, _, _)| span); - for (span, to_remove, suggestion) in suggestions { - err.span_suggestion_verbose( - span, - &format!("consider removing the {to_remove}"), - suggestion, - Applicability::MachineApplicable, - ); + for (span, msg, suggestion) in suggestions { + err.span_suggestion_verbose(span, &msg, suggestion, Applicability::MachineApplicable); } } diff --git a/src/test/ui/borrowck/borrowck-move-error-with-note.fixed b/src/test/ui/borrowck/borrowck-move-error-with-note.fixed new file mode 100644 index 00000000000..74b3ee2ebdf --- /dev/null +++ b/src/test/ui/borrowck/borrowck-move-error-with-note.fixed @@ -0,0 +1,56 @@ +// run-rustfix +#![allow(unused)] +enum Foo { + Foo1(Box<u32>, Box<u32>), + Foo2(Box<u32>), + Foo3, +} + + + +fn blah() { + let f = &Foo::Foo1(Box::new(1), Box::new(2)); + match &*f { //~ ERROR cannot move out of + Foo::Foo1(num1, + num2) => (), + Foo::Foo2(num) => (), + Foo::Foo3 => () + } +} + +struct S { + f: String, + g: String +} +impl Drop for S { + fn drop(&mut self) { println!("{}", self.f); } +} + +fn move_in_match() { + match (S {f: "foo".to_string(), g: "bar".to_string()}) { + //~^ ERROR cannot move out of type `S`, which implements the `Drop` trait + S { + f: ref _s, + g: ref _t + } => {} + } +} + +// from issue-8064 +struct A { + a: Box<isize>, +} + +fn free<T>(_: T) {} + +fn blah2() { + let a = &A { a: Box::new(1) }; + match &a.a { //~ ERROR cannot move out of + n => { + free(n) + } + } + free(a) +} + +fn main() {} diff --git a/src/test/ui/borrowck/borrowck-move-error-with-note.rs b/src/test/ui/borrowck/borrowck-move-error-with-note.rs index ef38cbb63a5..f336ac4f994 100644 --- a/src/test/ui/borrowck/borrowck-move-error-with-note.rs +++ b/src/test/ui/borrowck/borrowck-move-error-with-note.rs @@ -1,3 +1,5 @@ +// run-rustfix +#![allow(unused)] enum Foo { Foo1(Box<u32>, Box<u32>), Foo2(Box<u32>), diff --git a/src/test/ui/borrowck/borrowck-move-error-with-note.stderr b/src/test/ui/borrowck/borrowck-move-error-with-note.stderr index 564e8470728..9b5cf712b69 100644 --- a/src/test/ui/borrowck/borrowck-move-error-with-note.stderr +++ b/src/test/ui/borrowck/borrowck-move-error-with-note.stderr @@ -1,5 +1,5 @@ error[E0507]: cannot move out of `f` as enum variant `Foo1` which is behind a shared reference - --> $DIR/borrowck-move-error-with-note.rs:11:11 + --> $DIR/borrowck-move-error-with-note.rs:13:11 | LL | match *f { | ^^ @@ -17,7 +17,7 @@ LL | match &*f { | + error[E0509]: cannot move out of type `S`, which implements the `Drop` trait - --> $DIR/borrowck-move-error-with-note.rs:28:11 + --> $DIR/borrowck-move-error-with-note.rs:30:11 | LL | match (S {f: "foo".to_string(), g: "bar".to_string()}) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here @@ -28,9 +28,17 @@ LL | g: _t | -- ...and here | = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider borrowing the pattern binding + | +LL | f: ref _s, + | +++ +help: consider borrowing the pattern binding + | +LL | g: ref _t + | +++ error[E0507]: cannot move out of `a.a` which is behind a shared reference - --> $DIR/borrowck-move-error-with-note.rs:46:11 + --> $DIR/borrowck-move-error-with-note.rs:48:11 | LL | match a.a { | ^^^ diff --git a/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.fixed b/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.fixed new file mode 100644 index 00000000000..c463c655938 --- /dev/null +++ b/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.fixed @@ -0,0 +1,24 @@ +// run-rustfix +#![allow(unused)] +struct S {f:String} +impl Drop for S { + fn drop(&mut self) { println!("{}", self.f); } +} + +fn move_in_match() { + match (S {f:"foo".to_string()}) { + //~^ ERROR [E0509] + S {f:ref _s} => {} + } +} + +fn move_in_let() { + let S {f:ref _s} = S {f:"foo".to_string()}; + //~^ ERROR [E0509] +} + +fn move_in_fn_arg(S {f:ref _s}: S) { + //~^ ERROR [E0509] +} + +fn main() {} diff --git a/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.rs b/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.rs index a429f4bc33b..93183062d61 100644 --- a/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.rs +++ b/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.rs @@ -1,3 +1,5 @@ +// run-rustfix +#![allow(unused)] struct S {f:String} impl Drop for S { fn drop(&mut self) { println!("{}", self.f); } diff --git a/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.stderr b/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.stderr index 7b00ac9f1c3..58f706c65ff 100644 --- a/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.stderr +++ b/src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.stderr @@ -1,5 +1,5 @@ error[E0509]: cannot move out of type `S`, which implements the `Drop` trait - --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:7:11 + --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:9:11 | LL | match (S {f:"foo".to_string()}) { | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here @@ -9,18 +9,28 @@ LL | S {f:_s} => {} | | | data moved here | move occurs because `_s` has type `String`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | S {f:ref _s} => {} + | +++ error[E0509]: cannot move out of type `S`, which implements the `Drop` trait - --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:14:20 + --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:16:20 | LL | let S {f:_s} = S {f:"foo".to_string()}; | -- ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here | | | data moved here | move occurs because `_s` has type `String`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | let S {f:ref _s} = S {f:"foo".to_string()}; + | +++ error[E0509]: cannot move out of type `S`, which implements the `Drop` trait - --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:18:19 + --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:20:19 | LL | fn move_in_fn_arg(S {f:_s}: S) { | ^^^^^--^ @@ -28,6 +38,11 @@ LL | fn move_in_fn_arg(S {f:_s}: S) { | | data moved here | | move occurs because `_s` has type `String`, which does not implement the `Copy` trait | cannot move out of here + | +help: consider borrowing the pattern binding + | +LL | fn move_in_fn_arg(S {f:ref _s}: S) { + | +++ error: aborting due to 3 previous errors diff --git a/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.fixed b/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.fixed new file mode 100644 index 00000000000..bc2ddf85fb4 --- /dev/null +++ b/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.fixed @@ -0,0 +1,24 @@ +// run-rustfix +#![allow(unused)] +struct S(String); +impl Drop for S { + fn drop(&mut self) { } +} + +fn move_in_match() { + match S("foo".to_string()) { + //~^ ERROR cannot move out of type `S`, which implements the `Drop` trait + S(ref _s) => {} + } +} + +fn move_in_let() { + let S(ref _s) = S("foo".to_string()); + //~^ ERROR cannot move out of type `S`, which implements the `Drop` trait +} + +fn move_in_fn_arg(S(ref _s): S) { + //~^ ERROR cannot move out of type `S`, which implements the `Drop` trait +} + +fn main() {} diff --git a/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.rs b/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.rs index 5bd32f82ebc..f050bce8740 100644 --- a/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.rs +++ b/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.rs @@ -1,3 +1,5 @@ +// run-rustfix +#![allow(unused)] struct S(String); impl Drop for S { fn drop(&mut self) { } diff --git a/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.stderr b/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.stderr index f00181b7468..160a1f99f63 100644 --- a/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.stderr +++ b/src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.stderr @@ -1,5 +1,5 @@ error[E0509]: cannot move out of type `S`, which implements the `Drop` trait - --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:7:11 + --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:9:11 | LL | match S("foo".to_string()) { | ^^^^^^^^^^^^^^^^^^^^ cannot move out of here @@ -9,18 +9,28 @@ LL | S(_s) => {} | | | data moved here | move occurs because `_s` has type `String`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | S(ref _s) => {} + | +++ error[E0509]: cannot move out of type `S`, which implements the `Drop` trait - --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:14:17 + --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:16:17 | LL | let S(_s) = S("foo".to_string()); | -- ^^^^^^^^^^^^^^^^^^^^ cannot move out of here | | | data moved here | move occurs because `_s` has type `String`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | let S(ref _s) = S("foo".to_string()); + | +++ error[E0509]: cannot move out of type `S`, which implements the `Drop` trait - --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:18:19 + --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:20:19 | LL | fn move_in_fn_arg(S(_s): S) { | ^^--^ @@ -28,6 +38,11 @@ LL | fn move_in_fn_arg(S(_s): S) { | | data moved here | | move occurs because `_s` has type `String`, which does not implement the `Copy` trait | cannot move out of here + | +help: consider borrowing the pattern binding + | +LL | fn move_in_fn_arg(S(ref _s): S) { + | +++ error: aborting due to 3 previous errors diff --git a/src/test/ui/borrowck/issue-51301.stderr b/src/test/ui/borrowck/issue-51301.stderr index f3decf7a991..6ec920cb81f 100644 --- a/src/test/ui/borrowck/issue-51301.stderr +++ b/src/test/ui/borrowck/issue-51301.stderr @@ -6,6 +6,11 @@ LL | .find(|(&event_type, _)| event == event_type) | | | data moved here | move occurs because `event_type` has type `EventType`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | .find(|(&ref event_type, _)| event == event_type) + | +++ error: aborting due to previous error diff --git a/src/test/ui/borrowck/issue-51415.fixed b/src/test/ui/borrowck/issue-51415.fixed new file mode 100644 index 00000000000..92943f6c9ec --- /dev/null +++ b/src/test/ui/borrowck/issue-51415.fixed @@ -0,0 +1,12 @@ +// run-rustfix +// Regression test for #51415: match default bindings were failing to +// see the "move out" implied by `&s` below. + +fn main() { + let a = vec![String::from("a")]; + let opt = a.iter().enumerate().find(|(_, &ref s)| { + //~^ ERROR cannot move out + *s == String::from("d") + }).map(|(i, _)| i); + println!("{:?}", opt); +} diff --git a/src/test/ui/borrowck/issue-51415.rs b/src/test/ui/borrowck/issue-51415.rs index f031308fb78..56ed57a61a0 100644 --- a/src/test/ui/borrowck/issue-51415.rs +++ b/src/test/ui/borrowck/issue-51415.rs @@ -1,3 +1,4 @@ +// run-rustfix // Regression test for #51415: match default bindings were failing to // see the "move out" implied by `&s` below. diff --git a/src/test/ui/borrowck/issue-51415.stderr b/src/test/ui/borrowck/issue-51415.stderr index a88819efcf7..0d486b45592 100644 --- a/src/test/ui/borrowck/issue-51415.stderr +++ b/src/test/ui/borrowck/issue-51415.stderr @@ -1,11 +1,16 @@ error[E0507]: cannot move out of a shared reference - --> $DIR/issue-51415.rs:6:42 + --> $DIR/issue-51415.rs:7:42 | LL | let opt = a.iter().enumerate().find(|(_, &s)| { | ^^^^^-^ | | | data moved here | move occurs because `s` has type `String`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | let opt = a.iter().enumerate().find(|(_, &ref s)| { + | +++ error: aborting due to previous error diff --git a/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.fixed b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.fixed new file mode 100644 index 00000000000..ae0a84eea4d --- /dev/null +++ b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.fixed @@ -0,0 +1,21 @@ +// run-rustfix +struct X { + x: String, +} + +impl Drop for X { + fn drop(&mut self) { + println!("value: {}", self.x); + } +} + +fn unwrap(x: X) -> String { + let X { x: ref y } = x; //~ ERROR cannot move out of type + y.to_string() +} + +fn main() { + let x = X { x: "hello".to_string() }; + let y = unwrap(x); + println!("contents: {}", y); +} diff --git a/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.rs b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.rs index 8e394498a23..c8db7861068 100644 --- a/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.rs +++ b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.rs @@ -1,3 +1,4 @@ +// run-rustfix struct X { x: String, } @@ -10,7 +11,7 @@ impl Drop for X { fn unwrap(x: X) -> String { let X { x: y } = x; //~ ERROR cannot move out of type - y + y.to_string() } fn main() { diff --git a/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.stderr b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.stderr index cda81d13669..596ad4bf784 100644 --- a/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.stderr +++ b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.stderr @@ -1,11 +1,16 @@ error[E0509]: cannot move out of type `X`, which implements the `Drop` trait - --> $DIR/disallowed-deconstructing-destructing-struct-let.rs:12:22 + --> $DIR/disallowed-deconstructing-destructing-struct-let.rs:13:22 | LL | let X { x: y } = x; | - ^ cannot move out of here | | | data moved here | move occurs because `y` has type `String`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | let X { x: ref y } = x; + | +++ error: aborting due to previous error diff --git a/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.fixed b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.fixed new file mode 100644 index 00000000000..c8a451efeb2 --- /dev/null +++ b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.fixed @@ -0,0 +1,19 @@ +// run-rustfix +struct X { + x: String, +} + +impl Drop for X { + fn drop(&mut self) { + println!("value: {}", self.x); + } +} + +fn main() { + let x = X { x: "hello".to_string() }; + + match x { + //~^ ERROR cannot move out of type `X`, which implements the `Drop` trait + X { x: ref y } => println!("contents: {}", y) + } +} diff --git a/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.rs b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.rs index 9c996a93b95..815567ffec3 100644 --- a/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.rs +++ b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.rs @@ -1,3 +1,4 @@ +// run-rustfix struct X { x: String, } diff --git a/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.stderr b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.stderr index 70cdd6446c8..e32a4dd4411 100644 --- a/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.stderr +++ b/src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.stderr @@ -1,5 +1,5 @@ error[E0509]: cannot move out of type `X`, which implements the `Drop` trait - --> $DIR/disallowed-deconstructing-destructing-struct-match.rs:14:11 + --> $DIR/disallowed-deconstructing-destructing-struct-match.rs:15:11 | LL | match x { | ^ cannot move out of here @@ -9,6 +9,11 @@ LL | X { x: y } => println!("contents: {}", y) | | | data moved here | move occurs because `y` has type `String`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | X { x: ref y } => println!("contents: {}", y) + | +++ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-12567.stderr b/src/test/ui/issues/issue-12567.stderr index 3ce659ccd14..7fa06825f0f 100644 --- a/src/test/ui/issues/issue-12567.stderr +++ b/src/test/ui/issues/issue-12567.stderr @@ -11,6 +11,14 @@ LL | (&[hd1, ..], &[hd2, ..]) | --- ...and here | = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider borrowing the pattern binding + | +LL | (&[], &[ref hd, ..]) | (&[hd, ..], &[]) + | +++ +help: consider borrowing the pattern binding + | +LL | (&[ref hd1, ..], &[hd2, ..]) + | +++ error[E0508]: cannot move out of type `[T]`, a non-copy slice --> $DIR/issue-12567.rs:2:11 @@ -25,6 +33,14 @@ LL | (&[hd1, ..], &[hd2, ..]) | --- ...and here | = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider borrowing the pattern binding + | +LL | (&[], &[ref hd, ..]) | (&[hd, ..], &[]) + | +++ +help: consider borrowing the pattern binding + | +LL | (&[hd1, ..], &[ref hd2, ..]) + | +++ error: aborting due to 2 previous errors diff --git a/src/test/ui/moves/move-out-of-slice-1.stderr b/src/test/ui/moves/move-out-of-slice-1.stderr index ce5ddb3e183..5a0357cf567 100644 --- a/src/test/ui/moves/move-out-of-slice-1.stderr +++ b/src/test/ui/moves/move-out-of-slice-1.stderr @@ -8,6 +8,11 @@ LL | box [a] => {}, | | | data moved here | move occurs because `a` has type `A`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | box [ref a] => {}, + | +++ error: aborting due to previous error diff --git a/src/test/ui/moves/move-out-of-slice-2.rs b/src/test/ui/moves/move-out-of-slice-2.rs index 59c02d42bf1..2f7394fbfd3 100644 --- a/src/test/ui/moves/move-out-of-slice-2.rs +++ b/src/test/ui/moves/move-out-of-slice-2.rs @@ -1,5 +1,6 @@ #![feature(unsized_locals)] //~^ WARN the feature `unsized_locals` is incomplete +#![allow(unused)] struct A; #[derive(Clone, Copy)] diff --git a/src/test/ui/moves/move-out-of-slice-2.stderr b/src/test/ui/moves/move-out-of-slice-2.stderr index 46357ce6f2e..b46854cd6b4 100644 --- a/src/test/ui/moves/move-out-of-slice-2.stderr +++ b/src/test/ui/moves/move-out-of-slice-2.stderr @@ -8,7 +8,7 @@ LL | #![feature(unsized_locals)] = note: `#[warn(incomplete_features)]` on by default error[E0508]: cannot move out of type `[A]`, a non-copy slice - --> $DIR/move-out-of-slice-2.rs:10:11 + --> $DIR/move-out-of-slice-2.rs:11:11 | LL | match *a { | ^^ cannot move out of here @@ -18,9 +18,14 @@ LL | [a @ ..] => {} | | | data moved here | move occurs because `a` has type `[A]`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | [ref a @ ..] => {} + | +++ error[E0508]: cannot move out of type `[A]`, a non-copy slice - --> $DIR/move-out-of-slice-2.rs:16:11 + --> $DIR/move-out-of-slice-2.rs:17:11 | LL | match *b { | ^^ cannot move out of here @@ -30,9 +35,14 @@ LL | [_, _, b @ .., _] => {} | | | data moved here | move occurs because `b` has type `[A]`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | [_, _, ref b @ .., _] => {} + | +++ error[E0508]: cannot move out of type `[C]`, a non-copy slice - --> $DIR/move-out-of-slice-2.rs:24:11 + --> $DIR/move-out-of-slice-2.rs:25:11 | LL | match *c { | ^^ cannot move out of here @@ -42,9 +52,14 @@ LL | [c @ ..] => {} | | | data moved here | move occurs because `c` has type `[C]`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | [ref c @ ..] => {} + | +++ error[E0508]: cannot move out of type `[C]`, a non-copy slice - --> $DIR/move-out-of-slice-2.rs:30:11 + --> $DIR/move-out-of-slice-2.rs:31:11 | LL | match *d { | ^^ cannot move out of here @@ -54,6 +69,11 @@ LL | [_, _, d @ .., _] => {} | | | data moved here | move occurs because `d` has type `[C]`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | [_, _, ref d @ .., _] => {} + | +++ error: aborting due to 4 previous errors; 1 warning emitted diff --git a/src/test/ui/nll/move-errors.stderr b/src/test/ui/nll/move-errors.stderr index afea8c1ff6c..1ec19b303e8 100644 --- a/src/test/ui/nll/move-errors.stderr +++ b/src/test/ui/nll/move-errors.stderr @@ -81,6 +81,11 @@ LL | let C(D(s)) = c; | | | data moved here | move occurs because `s` has type `String`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | let C(D(ref s)) = c; + | +++ error[E0507]: cannot move out of `*a` which is behind a shared reference --> $DIR/move-errors.rs:51:9 @@ -116,6 +121,11 @@ LL | B::U(D(s)) => (), | | | data moved here | move occurs because `s` has type `String`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | B::U(D(ref s)) => (), + | +++ error[E0509]: cannot move out of type `D`, which implements the `Drop` trait --> $DIR/move-errors.rs:92:11 @@ -128,6 +138,11 @@ LL | (D(s), &t) => (), | | | data moved here | move occurs because `s` has type `String`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | (D(ref s), &t) => (), + | +++ error[E0507]: cannot move out of `*x.1` which is behind a shared reference --> $DIR/move-errors.rs:92:11 @@ -140,6 +155,11 @@ LL | (D(s), &t) => (), | | | data moved here | move occurs because `t` has type `String`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | (D(s), &ref t) => (), + | +++ error[E0509]: cannot move out of type `F`, which implements the `Drop` trait --> $DIR/move-errors.rs:102:11 @@ -153,6 +173,14 @@ LL | F(s, mut t) => (), | data moved here | = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider borrowing the pattern binding + | +LL | F(ref s, mut t) => (), + | +++ +help: consider borrowing the pattern binding + | +LL | F(s, ref mut t) => (), + | +++ error[E0507]: cannot move out of `x` as enum variant `Err` which is behind a shared reference --> $DIR/move-errors.rs:110:11 diff --git a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.fixed b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.fixed new file mode 100644 index 00000000000..5f04fc83d37 --- /dev/null +++ b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.fixed @@ -0,0 +1,12 @@ +// run-rustfix +#![allow(unused_variables)] +fn main() { + struct U; + + // A tuple is a "non-reference pattern". + // A `mut` binding pattern resets the binding mode to by-value. + + let mut p = (U, U); + let (a, ref mut b) = &mut p; + //~^ ERROR cannot move out of a mutable reference +} diff --git a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.rs b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.rs new file mode 100644 index 00000000000..5dc1ae2feb5 --- /dev/null +++ b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.rs @@ -0,0 +1,12 @@ +// run-rustfix +#![allow(unused_variables)] +fn main() { + struct U; + + // A tuple is a "non-reference pattern". + // A `mut` binding pattern resets the binding mode to by-value. + + let mut p = (U, U); + let (a, mut b) = &mut p; + //~^ ERROR cannot move out of a mutable reference +} diff --git a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.stderr b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.stderr new file mode 100644 index 00000000000..d3ab533e35e --- /dev/null +++ b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes-fixable.stderr @@ -0,0 +1,17 @@ +error[E0507]: cannot move out of a mutable reference + --> $DIR/move-ref-patterns-default-binding-modes-fixable.rs:10:22 + | +LL | let (a, mut b) = &mut p; + | ----- ^^^^^^ + | | + | data moved here + | move occurs because `b` has type `U`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | let (a, ref mut b) = &mut p; + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.rs b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.rs index 1dd66aad57a..6c913c24513 100644 --- a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.rs +++ b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.rs @@ -7,8 +7,4 @@ fn main() { let p = (U, U); let (a, mut b) = &p; //~^ ERROR cannot move out of a shared reference - - let mut p = (U, U); - let (a, mut b) = &mut p; - //~^ ERROR cannot move out of a mutable reference } diff --git a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.stderr b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.stderr index 6952c743a30..65030b62250 100644 --- a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.stderr +++ b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.stderr @@ -6,16 +6,12 @@ LL | let (a, mut b) = &p; | | | data moved here | move occurs because `b` has type `U`, which does not implement the `Copy` trait - -error[E0507]: cannot move out of a mutable reference - --> $DIR/move-ref-patterns-default-binding-modes.rs:12:22 | -LL | let (a, mut b) = &mut p; - | ----- ^^^^^^ - | | - | data moved here - | move occurs because `b` has type `U`, which does not implement the `Copy` trait +help: consider borrowing the pattern binding + | +LL | let (a, ref mut b) = &p; + | +++ -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/rfc-2005-default-binding-mode/for.stderr b/src/test/ui/rfc-2005-default-binding-mode/for.stderr index 9cc20a7bf31..07991af6ef9 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/for.stderr +++ b/src/test/ui/rfc-2005-default-binding-mode/for.stderr @@ -6,6 +6,11 @@ LL | for (n, mut m) in &tups { | | | data moved here | move occurs because `m` has type `Foo`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | for (n, ref mut m) in &tups { + | +++ error: aborting due to previous error diff --git a/src/test/ui/suggestions/dont-suggest-ref/simple.rs b/src/test/ui/suggestions/dont-suggest-ref/simple.rs index 1de612abbcd..e0c49699740 100644 --- a/src/test/ui/suggestions/dont-suggest-ref/simple.rs +++ b/src/test/ui/suggestions/dont-suggest-ref/simple.rs @@ -219,31 +219,42 @@ pub fn main() { let (&X(_t),) = (&x.clone(),); //~^ ERROR cannot move + //~| HELP consider borrowing the pattern binding if let (&Either::One(_t),) = (&e.clone(),) { } //~^ ERROR cannot move + //~| HELP consider borrowing the pattern binding while let (&Either::One(_t),) = (&e.clone(),) { } //~^ ERROR cannot move + //~| HELP consider borrowing the pattern binding match (&e.clone(),) { //~^ ERROR cannot move (&Either::One(_t),) + //~^ HELP consider borrowing the pattern binding | (&Either::Two(_t),) => (), } fn f3((&X(_t),): (&X,)) { } //~^ ERROR cannot move + //~| HELP consider borrowing the pattern binding let (&mut X(_t),) = (&mut xm.clone(),); //~^ ERROR cannot move + //~| HELP consider borrowing the pattern binding if let (&mut Either::One(_t),) = (&mut em.clone(),) { } //~^ ERROR cannot move + //~| HELP consider borrowing the pattern binding while let (&mut Either::One(_t),) = (&mut em.clone(),) { } //~^ ERROR cannot move + //~| HELP consider borrowing the pattern binding match (&mut em.clone(),) { //~^ ERROR cannot move (&mut Either::One(_t),) => (), + //~^ HELP consider borrowing the pattern binding (&mut Either::Two(_t),) => (), + //~^ HELP consider borrowing the pattern binding } fn f4((&mut X(_t),): (&mut X,)) { } //~^ ERROR cannot move + //~| HELP consider borrowing the pattern binding // move from &Either/&X value @@ -319,6 +330,7 @@ struct Testing { fn testing(a: &Testing) { let Some(_s) = a.a else { //~^ ERROR cannot move + //~| HELP consider borrowing the pattern binding return; }; } diff --git a/src/test/ui/suggestions/dont-suggest-ref/simple.stderr b/src/test/ui/suggestions/dont-suggest-ref/simple.stderr index 400eee83311..39fd1c47697 100644 --- a/src/test/ui/suggestions/dont-suggest-ref/simple.stderr +++ b/src/test/ui/suggestions/dont-suggest-ref/simple.stderr @@ -566,27 +566,42 @@ LL | let (&X(_t),) = (&x.clone(),); | | | data moved here | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | let (&X(ref _t),) = (&x.clone(),); + | +++ error[E0507]: cannot move out of a shared reference - --> $DIR/simple.rs:222:34 + --> $DIR/simple.rs:223:34 | LL | if let (&Either::One(_t),) = (&e.clone(),) { } | -- ^^^^^^^^^^^^^ | | | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | if let (&Either::One(ref _t),) = (&e.clone(),) { } + | +++ error[E0507]: cannot move out of a shared reference - --> $DIR/simple.rs:224:37 + --> $DIR/simple.rs:226:37 | LL | while let (&Either::One(_t),) = (&e.clone(),) { } | -- ^^^^^^^^^^^^^ | | | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | while let (&Either::One(ref _t),) = (&e.clone(),) { } + | +++ error[E0507]: cannot move out of a shared reference - --> $DIR/simple.rs:226:11 + --> $DIR/simple.rs:229:11 | LL | match (&e.clone(),) { | ^^^^^^^^^^^^^ @@ -596,49 +611,78 @@ LL | (&Either::One(_t),) | | | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | (&Either::One(ref _t),) + | +++ error[E0507]: cannot move out of a mutable reference - --> $DIR/simple.rs:234:25 + --> $DIR/simple.rs:239:25 | LL | let (&mut X(_t),) = (&mut xm.clone(),); | -- ^^^^^^^^^^^^^^^^^^ | | | data moved here | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | let (&mut X(ref _t),) = (&mut xm.clone(),); + | +++ error[E0507]: cannot move out of a mutable reference - --> $DIR/simple.rs:236:38 + --> $DIR/simple.rs:242:38 | LL | if let (&mut Either::One(_t),) = (&mut em.clone(),) { } | -- ^^^^^^^^^^^^^^^^^^ | | | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | if let (&mut Either::One(ref _t),) = (&mut em.clone(),) { } + | +++ error[E0507]: cannot move out of a mutable reference - --> $DIR/simple.rs:238:41 + --> $DIR/simple.rs:245:41 | LL | while let (&mut Either::One(_t),) = (&mut em.clone(),) { } | -- ^^^^^^^^^^^^^^^^^^ | | | data moved here | move occurs because `_t` has type `X`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | while let (&mut Either::One(ref _t),) = (&mut em.clone(),) { } + | +++ error[E0507]: cannot move out of a mutable reference - --> $DIR/simple.rs:240:11 + --> $DIR/simple.rs:248:11 | LL | match (&mut em.clone(),) { | ^^^^^^^^^^^^^^^^^^ LL | LL | (&mut Either::One(_t),) => (), | -- data moved here +LL | LL | (&mut Either::Two(_t),) => (), | -- ...and here | = note: move occurs because these variables have types that don't implement the `Copy` trait +help: consider borrowing the pattern binding + | +LL | (&mut Either::One(ref _t),) => (), + | +++ +help: consider borrowing the pattern binding + | +LL | (&mut Either::Two(ref _t),) => (), + | +++ error[E0507]: cannot move out of a shared reference - --> $DIR/simple.rs:250:18 + --> $DIR/simple.rs:261:18 | LL | let &X(_t) = &x; | -- ^^ @@ -653,7 +697,7 @@ LL + let X(_t) = &x; | error[E0507]: cannot move out of a shared reference - --> $DIR/simple.rs:253:31 + --> $DIR/simple.rs:264:31 | LL | if let &Either::One(_t) = &e { } | -- ^^ @@ -668,7 +712,7 @@ LL + if let Either::One(_t) = &e { } | error[E0507]: cannot move out of a shared reference - --> $DIR/simple.rs:256:34 + --> $DIR/simple.rs:267:34 | LL | while let &Either::One(_t) = &e { } | -- ^^ @@ -683,7 +727,7 @@ LL + while let Either::One(_t) = &e { } | error[E0507]: cannot move out of a shared reference - --> $DIR/simple.rs:259:11 + --> $DIR/simple.rs:270:11 | LL | match &e { | ^^ @@ -701,7 +745,7 @@ LL + Either::One(_t) | error[E0507]: cannot move out of a shared reference - --> $DIR/simple.rs:266:11 + --> $DIR/simple.rs:277:11 | LL | match &e { | ^^ @@ -719,7 +763,7 @@ LL + Either::One(_t) => (), | error[E0507]: cannot move out of a shared reference - --> $DIR/simple.rs:272:11 + --> $DIR/simple.rs:283:11 | LL | match &e { | ^^ @@ -737,7 +781,7 @@ LL + Either::One(_t) => (), | error[E0507]: cannot move out of a mutable reference - --> $DIR/simple.rs:279:22 + --> $DIR/simple.rs:290:22 | LL | let &mut X(_t) = &mut xm; | -- ^^^^^^^ @@ -752,7 +796,7 @@ LL + let mut X(_t) = &mut xm; | error[E0507]: cannot move out of a mutable reference - --> $DIR/simple.rs:282:35 + --> $DIR/simple.rs:293:35 | LL | if let &mut Either::One(_t) = &mut em { } | -- ^^^^^^^ @@ -767,7 +811,7 @@ LL + if let mut Either::One(_t) = &mut em { } | error[E0507]: cannot move out of a mutable reference - --> $DIR/simple.rs:285:38 + --> $DIR/simple.rs:296:38 | LL | while let &mut Either::One(_t) = &mut em { } | -- ^^^^^^^ @@ -782,7 +826,7 @@ LL + while let mut Either::One(_t) = &mut em { } | error[E0507]: cannot move out of a mutable reference - --> $DIR/simple.rs:288:11 + --> $DIR/simple.rs:299:11 | LL | match &mut em { | ^^^^^^^ @@ -800,7 +844,7 @@ LL + mut Either::One(_t) | error[E0507]: cannot move out of a mutable reference - --> $DIR/simple.rs:295:11 + --> $DIR/simple.rs:306:11 | LL | match &mut em { | ^^^^^^^ @@ -818,7 +862,7 @@ LL + mut Either::One(_t) => (), | error[E0507]: cannot move out of a mutable reference - --> $DIR/simple.rs:301:11 + --> $DIR/simple.rs:312:11 | LL | match &mut em { | ^^^^^^^ @@ -836,7 +880,7 @@ LL + mut Either::One(_t) => (), | error[E0507]: cannot move out of a mutable reference - --> $DIR/simple.rs:307:11 + --> $DIR/simple.rs:318:11 | LL | match &mut em { | ^^^^^^^ @@ -884,31 +928,46 @@ LL + fn f2(mut X(_t): &mut X) { } | error[E0507]: cannot move out of a shared reference - --> $DIR/simple.rs:231:11 + --> $DIR/simple.rs:235:11 | LL | fn f3((&X(_t),): (&X,)) { } | ^^^^--^^^ | | | data moved here | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | fn f3((&X(ref _t),): (&X,)) { } + | +++ error[E0507]: cannot move out of a mutable reference - --> $DIR/simple.rs:245:11 + --> $DIR/simple.rs:255:11 | LL | fn f4((&mut X(_t),): (&mut X,)) { } | ^^^^^^^^--^^^ | | | data moved here | move occurs because `_t` has type `Y`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | fn f4((&mut X(ref _t),): (&mut X,)) { } + | +++ error[E0507]: cannot move out of `a.a` as enum variant `Some` which is behind a shared reference - --> $DIR/simple.rs:320:20 + --> $DIR/simple.rs:331:20 | LL | let Some(_s) = a.a else { | -- ^^^ | | | data moved here | move occurs because `_s` has type `String`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | let Some(ref _s) = a.a else { + | +++ error: aborting due to 61 previous errors diff --git a/src/test/ui/suggestions/option-content-move-from-tuple-match.stderr b/src/test/ui/suggestions/option-content-move-from-tuple-match.stderr index debb8cabaea..97d05d9dcff 100644 --- a/src/test/ui/suggestions/option-content-move-from-tuple-match.stderr +++ b/src/test/ui/suggestions/option-content-move-from-tuple-match.stderr @@ -9,6 +9,11 @@ LL | (None, &c) => &c.unwrap(), | | | data moved here | move occurs because `c` has type `Option<String>`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | (None, &ref c) => &c.unwrap(), + | +++ error: aborting due to previous error