diff --git a/src/librustc_mir/borrow_check/diagnostics/mod.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs index edfaae533ef03..c5d601f06bde7 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mod.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs @@ -776,13 +776,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } - let normal_ret = if let [ProjectionElem::Downcast(..), ProjectionElem::Field(_, _)] = - moved_place.projection - { - PatUse(stmt.source_info.span) - } else { - OtherUse(stmt.source_info.span) - }; + let normal_ret = + if moved_place.projection.iter().any(|p| matches!(p, ProjectionElem::Downcast(..))) { + PatUse(stmt.source_info.span) + } else { + OtherUse(stmt.source_info.span) + }; // We are trying to find MIR of the form: // ``` diff --git a/src/test/ui/borrowck/move-in-pattern-mut.rs b/src/test/ui/borrowck/move-in-pattern-mut.rs new file mode 100644 index 0000000000000..175eb3b7a04d1 --- /dev/null +++ b/src/test/ui/borrowck/move-in-pattern-mut.rs @@ -0,0 +1,23 @@ +// Issue #63988 +#[derive(Debug)] +struct S; +fn foo(_: Option) {} + +enum E { + V { + s: S, + } +} +fn bar(_: E) {} + +fn main() { + let s = Some(S); + if let Some(mut x) = s { + x = S; + } + foo(s); //~ ERROR use of moved value: `s` + let mut e = E::V { s: S }; + let E::V { s: mut x } = e; + x = S; + bar(e); //~ ERROR use of moved value: `e` +} diff --git a/src/test/ui/borrowck/move-in-pattern-mut.stderr b/src/test/ui/borrowck/move-in-pattern-mut.stderr new file mode 100644 index 0000000000000..391638444c3bd --- /dev/null +++ b/src/test/ui/borrowck/move-in-pattern-mut.stderr @@ -0,0 +1,33 @@ +error[E0382]: use of moved value: `s` + --> $DIR/move-in-pattern-mut.rs:18:9 + | +LL | if let Some(mut x) = s { + | ----- value moved here +... +LL | foo(s); + | ^ value used here after partial move + | + = note: move occurs because value has type `S`, which does not implement the `Copy` trait +help: borrow this field in the pattern to avoid moving `s.0` + | +LL | if let Some(ref mut x) = s { + | ^^^ + +error[E0382]: use of moved value: `e` + --> $DIR/move-in-pattern-mut.rs:22:9 + | +LL | let E::V { s: mut x } = e; + | ----- value moved here +LL | x = S; +LL | bar(e); + | ^ value used here after partial move + | + = note: move occurs because value has type `S`, which does not implement the `Copy` trait +help: borrow this field in the pattern to avoid moving `e.s` + | +LL | let E::V { s: ref mut x } = e; + | ^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/borrowck/move-in-pattern.fixed b/src/test/ui/borrowck/move-in-pattern.fixed index c44d48163c0c0..f55fdcc5f90e8 100644 --- a/src/test/ui/borrowck/move-in-pattern.fixed +++ b/src/test/ui/borrowck/move-in-pattern.fixed @@ -4,10 +4,21 @@ struct S; fn foo(_: Option) {} +enum E { + V { + s: S, + } +} +fn bar(_: E) {} + fn main() { let s = Some(S); if let Some(ref x) = s { let _ = x; } foo(s); //~ ERROR use of moved value: `s` + let e = E::V { s: S }; + let E::V { s: ref x } = e; + let _ = x; + bar(e); //~ ERROR use of moved value: `e` } diff --git a/src/test/ui/borrowck/move-in-pattern.rs b/src/test/ui/borrowck/move-in-pattern.rs index 910afc01e070b..7ad04b9490c25 100644 --- a/src/test/ui/borrowck/move-in-pattern.rs +++ b/src/test/ui/borrowck/move-in-pattern.rs @@ -4,10 +4,21 @@ struct S; fn foo(_: Option) {} +enum E { + V { + s: S, + } +} +fn bar(_: E) {} + fn main() { let s = Some(S); if let Some(x) = s { let _ = x; } foo(s); //~ ERROR use of moved value: `s` + let e = E::V { s: S }; + let E::V { s: x } = e; + let _ = x; + bar(e); //~ ERROR use of moved value: `e` } diff --git a/src/test/ui/borrowck/move-in-pattern.stderr b/src/test/ui/borrowck/move-in-pattern.stderr index fc12b64ab5497..c5cb24455eb61 100644 --- a/src/test/ui/borrowck/move-in-pattern.stderr +++ b/src/test/ui/borrowck/move-in-pattern.stderr @@ -1,5 +1,5 @@ error[E0382]: use of moved value: `s` - --> $DIR/move-in-pattern.rs:12:9 + --> $DIR/move-in-pattern.rs:19:9 | LL | if let Some(x) = s { | - value moved here @@ -13,6 +13,21 @@ help: borrow this field in the pattern to avoid moving `s.0` LL | if let Some(ref x) = s { | ^^^ -error: aborting due to previous error +error[E0382]: use of moved value: `e` + --> $DIR/move-in-pattern.rs:23:9 + | +LL | let E::V { s: x } = e; + | - value moved here +LL | let _ = x; +LL | bar(e); + | ^ value used here after partial move + | + = note: move occurs because value has type `S`, which does not implement the `Copy` trait +help: borrow this field in the pattern to avoid moving `e.s` + | +LL | let E::V { s: ref x } = e; + | ^^^ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/moves/moves-based-on-type-cyclic-types-issue-4821.stderr b/src/test/ui/moves/moves-based-on-type-cyclic-types-issue-4821.stderr index fb8562d00ead1..952985fcddee6 100644 --- a/src/test/ui/moves/moves-based-on-type-cyclic-types-issue-4821.stderr +++ b/src/test/ui/moves/moves-based-on-type-cyclic-types-issue-4821.stderr @@ -8,6 +8,10 @@ LL | consume(node) + r | ^^^^ value used here after partial move | = note: move occurs because value has type `std::boxed::Box`, which does not implement the `Copy` trait +help: borrow this field in the pattern to avoid moving `node.next.0` + | +LL | Some(ref right) => consume(right), + | ^^^ error: aborting due to previous error diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr index f819e671436ec..5058998f2a7c1 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr @@ -357,6 +357,10 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} | value moved here | = note: move occurs because value has type `main::U`, which does not implement the `Copy` trait +help: borrow this field in the pattern to avoid moving the value + | +LL | a @ Some((ref mut b @ ref mut c, d @ ref e)) => {} + | ^^^ error[E0382]: use of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:38 @@ -379,6 +383,10 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} | value moved here | = note: move occurs because value has type `main::U`, which does not implement the `Copy` trait +help: borrow this field in the pattern to avoid moving the value + | +LL | a @ Some((mut b @ ref mut c, ref d @ ref e)) => {} + | ^^^ error[E0382]: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:71:30 @@ -412,6 +420,10 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} | value moved here | = note: move occurs because value has type `main::U`, which does not implement the `Copy` trait +help: borrow this field in the pattern to avoid moving the value + | +LL | a @ Some((ref mut b @ ref mut c, d @ ref e)) => {} + | ^^^ error[E0382]: use of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:83:38 @@ -434,6 +446,10 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} | value moved here | = note: move occurs because value has type `main::U`, which does not implement the `Copy` trait +help: borrow this field in the pattern to avoid moving the value + | +LL | a @ Some((mut b @ ref mut c, ref d @ ref e)) => {} + | ^^^ error[E0382]: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:93:30 diff --git a/src/test/ui/ref-suggestion.stderr b/src/test/ui/ref-suggestion.stderr index 9ff8e21bb58bd..97d2c174d9adb 100644 --- a/src/test/ui/ref-suggestion.stderr +++ b/src/test/ui/ref-suggestion.stderr @@ -28,6 +28,10 @@ LL | x; | ^ value used here after partial move | = note: move occurs because value has type `std::vec::Vec`, which does not implement the `Copy` trait +help: borrow this field in the pattern to avoid moving `x.0.0` + | +LL | (Some(ref y), ()) => {}, + | ^^^ error: aborting due to 3 previous errors