diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 49a1817311627..945733351ab6e 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -94,6 +94,12 @@ enum GroupedMoveError<'tcx> { }, } +struct PatternBindingInfo { + pat_span: Span, + binding_spans: Vec, + has_mutable_by_value_binding: bool, +} + impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { pub(crate) fn report_move_errors(&mut self) { let grouped_errors = self.group_move_errors(); @@ -678,8 +684,11 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { fn add_move_hints(&self, error: GroupedMoveError<'tcx>, err: &mut Diag<'_>, span: Span) { match error { GroupedMoveError::MovesFromPlace { mut binds_to, move_from, .. } => { - self.add_borrow_suggestions(err, span, !binds_to.is_empty()); + binds_to.sort(); + binds_to.dedup(); + if binds_to.is_empty() { + self.add_borrow_suggestions(err, span, false); let place_ty = move_from.ty(self.body, self.infcx.tcx).ty; let place_desc = match self.describe_place(move_from.as_ref()) { Some(desc) => format!("`{desc}`"), @@ -697,16 +706,30 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { span, }); } else { - binds_to.sort(); - binds_to.dedup(); - - self.add_move_error_details(err, &binds_to, &[]); + let binding_info = self.pattern_binding_info(&binds_to); + let suggest_pattern_binding = binding_info.as_ref().is_some_and(|info| { + self.should_suggest_pattern_binding_instead(span, info) + }); + let desugar_spans = if suggest_pattern_binding { + self.add_move_error_suggestions(err, &binds_to) + } else { + if self.should_suggest_borrow_instead(span, binding_info.as_ref()) { + self.add_borrow_suggestions(err, span, true); + } + None + }; + self.add_move_error_details( + err, + &binds_to, + desugar_spans.as_deref().unwrap_or_default(), + ); } } GroupedMoveError::MovesFromValue { mut binds_to, .. } => { binds_to.sort(); binds_to.dedup(); - let desugar_spans = self.add_move_error_suggestions(err, &binds_to); + let desugar_spans = + self.add_move_error_suggestions(err, &binds_to).unwrap_or_default(); self.add_move_error_details(err, &binds_to, &desugar_spans); } // No binding. Nothing to suggest. @@ -861,7 +884,102 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } } - fn add_move_error_suggestions(&self, err: &mut Diag<'_>, binds_to: &[Local]) -> Vec { + fn should_suggest_pattern_binding_instead( + &self, + span: Span, + binding_info: &PatternBindingInfo, + ) -> bool { + let Some(expr) = self.find_expr(span) else { + return false; + }; + + let typeck_results = self.infcx.tcx.typeck(self.mir_def_id()); + let projection_qualifies = match expr.kind { + hir::ExprKind::Field(base, ..) => { + !typeck_results.node_type_opt(base.hir_id).is_some_and(|base_ty| { + binding_info.has_mutable_by_value_binding + && matches!(base_ty.kind(), ty::Ref(_, _, hir::Mutability::Not)) + }) + } + hir::ExprKind::Index(base, ..) => typeck_results + .node_type_opt(base.hir_id) + .is_some_and(|base_ty| match base_ty.kind() { + ty::Ref(_, _, hir::Mutability::Not) | ty::RawPtr(..) => false, + ty::Ref(_, _, hir::Mutability::Mut) => { + binding_info.has_mutable_by_value_binding + } + _ => true, + }), + _ => false, + }; + if !projection_qualifies { + return false; + } + + let is_single_binding = binding_info.binding_spans.len() == 1 + && binding_info.binding_spans[0] == binding_info.pat_span; + !is_single_binding + } + + fn should_suggest_borrow_instead( + &self, + span: Span, + binding_info: Option<&PatternBindingInfo>, + ) -> bool { + if !binding_info.is_some_and(|info| info.has_mutable_by_value_binding) { + return true; + } + + let Some(expr) = self.find_expr(span) else { + return true; + }; + + let Some(base) = (match expr.kind { + hir::ExprKind::Field(base, _) | hir::ExprKind::Index(base, ..) => Some(base), + _ => None, + }) else { + return true; + }; + + !self + .infcx + .tcx + .typeck(self.mir_def_id()) + .node_type_opt(base.hir_id) + .is_some_and(|base_ty| matches!(base_ty.kind(), ty::Ref(_, _, hir::Mutability::Not))) + } + + fn pattern_binding_info(&self, binds_to: &[Local]) -> Option { + let mut pat_span = None; + let mut binding_spans = Vec::new(); + let mut has_mutable_by_value_binding = false; + for local in binds_to { + let bind_to = &self.body.local_decls[*local]; + if let LocalInfo::User(BindingForm::Var(VarBindingForm { + pat_span: pat_sp, + binding_mode, + .. + })) = *bind_to.local_info() + { + pat_span = Some(pat_sp); + binding_spans.push(bind_to.source_info.span); + has_mutable_by_value_binding |= + matches!(binding_mode, hir::BindingMode(hir::ByRef::No, hir::Mutability::Mut)); + } + } + + Some(PatternBindingInfo { + pat_span: pat_span?, + binding_spans, + has_mutable_by_value_binding, + }) + } + + fn add_move_error_suggestions( + &self, + err: &mut Diag<'_>, + binds_to: &[Local], + ) -> Option> { /// A HIR visitor to associate each binding with a `&` or `&mut` that could be removed to /// make it bind by reference instead (if possible) struct BindingFinder<'tcx> { @@ -964,27 +1082,20 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { self.has_adjustments = parent_has_adjustments; } } - let mut pat_span = None; - let mut binding_spans = Vec::new(); - for local in binds_to { - let bind_to = &self.body.local_decls[*local]; - if let LocalInfo::User(BindingForm::Var(VarBindingForm { pat_span: pat_sp, .. })) = - *bind_to.local_info() - { - pat_span = Some(pat_sp); - binding_spans.push(bind_to.source_info.span); - } - } - let Some(pat_span) = pat_span else { return Vec::new() }; + let Some(binding_info) = self.pattern_binding_info(binds_to) else { + return None; + }; let tcx = self.infcx.tcx; - let Some(body) = tcx.hir_maybe_body_owned_by(self.mir_def_id()) else { return Vec::new() }; + let Some(body) = tcx.hir_maybe_body_owned_by(self.mir_def_id()) else { + return None; + }; let typeck_results = self.infcx.tcx.typeck(self.mir_def_id()); let mut finder = BindingFinder { typeck_results, tcx, - pat_span, - binding_spans, + pat_span: binding_info.pat_span, + binding_spans: binding_info.binding_spans, found_pat: false, ref_pat: None, has_adjustments: false, @@ -1015,7 +1126,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { for (span, msg, suggestion) in suggestions { err.span_suggestion_verbose(span, msg, suggestion, Applicability::MachineApplicable); } - finder.desugar_binding_spans + + Some(finder.desugar_binding_spans) } fn add_move_error_details( diff --git a/tests/ui/binding/issue-40402-2.stderr b/tests/ui/binding/issue-40402-2.stderr index 987558903ee42..571dbe47d77b7 100644 --- a/tests/ui/binding/issue-40402-2.stderr +++ b/tests/ui/binding/issue-40402-2.stderr @@ -8,10 +8,14 @@ LL | let (a, b) = x[0]; | data moved here | = note: move occurs because these variables have types that don't implement the `Copy` trait -help: consider borrowing here +help: consider borrowing the pattern binding | -LL | let (a, b) = &x[0]; - | + +LL | let (ref a, b) = x[0]; + | +++ +help: consider borrowing the pattern binding + | +LL | let (a, ref b) = x[0]; + | +++ error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/deref-field-pattern-ref-suggestion-issue-146995.fixed b/tests/ui/borrowck/deref-field-pattern-ref-suggestion-issue-146995.fixed new file mode 100644 index 0000000000000..1e70933ae7381 --- /dev/null +++ b/tests/ui/borrowck/deref-field-pattern-ref-suggestion-issue-146995.fixed @@ -0,0 +1,40 @@ +//@ run-rustfix +#![allow(dead_code)] + +use std::ops::{Deref, DerefMut}; + +fn take(mut wrap: Wrap) { + if let Some(ref mut val) = wrap.field { + //~^ ERROR cannot move out of dereference of `Wrap` + val.0 = (); + } +} + +fn take_mut_ref_base(mut wrap: Wrap) { + if let Some(ref mut val) = (&mut wrap).field { + //~^ ERROR cannot move out of dereference of `Wrap` + val.0 = (); + } +} + +struct Wrap(T); +struct Struct { + field: Option, +} +struct NonCopy(()); + +impl Deref for Wrap { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for Wrap { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +fn main() {} diff --git a/tests/ui/borrowck/deref-field-pattern-ref-suggestion-issue-146995.rs b/tests/ui/borrowck/deref-field-pattern-ref-suggestion-issue-146995.rs new file mode 100644 index 0000000000000..ff9d4409b86bb --- /dev/null +++ b/tests/ui/borrowck/deref-field-pattern-ref-suggestion-issue-146995.rs @@ -0,0 +1,40 @@ +//@ run-rustfix +#![allow(dead_code)] + +use std::ops::{Deref, DerefMut}; + +fn take(mut wrap: Wrap) { + if let Some(mut val) = wrap.field { + //~^ ERROR cannot move out of dereference of `Wrap` + val.0 = (); + } +} + +fn take_mut_ref_base(mut wrap: Wrap) { + if let Some(mut val) = (&mut wrap).field { + //~^ ERROR cannot move out of dereference of `Wrap` + val.0 = (); + } +} + +struct Wrap(T); +struct Struct { + field: Option, +} +struct NonCopy(()); + +impl Deref for Wrap { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for Wrap { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +fn main() {} diff --git a/tests/ui/borrowck/deref-field-pattern-ref-suggestion-issue-146995.stderr b/tests/ui/borrowck/deref-field-pattern-ref-suggestion-issue-146995.stderr new file mode 100644 index 0000000000000..506ddd3bedae8 --- /dev/null +++ b/tests/ui/borrowck/deref-field-pattern-ref-suggestion-issue-146995.stderr @@ -0,0 +1,29 @@ +error[E0507]: cannot move out of dereference of `Wrap` + --> $DIR/deref-field-pattern-ref-suggestion-issue-146995.rs:7:28 + | +LL | if let Some(mut val) = wrap.field { + | ------- ^^^^^^^^^^ + | | + | data moved here because `val` has type `NonCopy`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | if let Some(ref mut val) = wrap.field { + | +++ + +error[E0507]: cannot move out of dereference of `Wrap` + --> $DIR/deref-field-pattern-ref-suggestion-issue-146995.rs:14:28 + | +LL | if let Some(mut val) = (&mut wrap).field { + | ------- ^^^^^^^^^^^^^^^^^ + | | + | data moved here because `val` has type `NonCopy`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | if let Some(ref mut val) = (&mut wrap).field { + | +++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/borrowck/deref-index-pattern-ref-suggestion.fixed b/tests/ui/borrowck/deref-index-pattern-ref-suggestion.fixed new file mode 100644 index 0000000000000..155a7c76e995d --- /dev/null +++ b/tests/ui/borrowck/deref-index-pattern-ref-suggestion.fixed @@ -0,0 +1,37 @@ +//@ run-rustfix +#![allow(dead_code)] + +use std::ops::{Deref, DerefMut}; + +fn take(mut wrap: Wrap<[Option; 1]>) { + if let Some(ref mut val) = wrap[0] { + //~^ ERROR cannot move out of type `[Option; 1]`, a non-copy array + val.0 = (); + } +} + +fn take_mut_ref_base(mut wrap: Wrap<[Option; 1]>) { + if let Some(ref mut val) = (&mut wrap)[0] { + //~^ ERROR cannot move out of type `[Option; 1]`, a non-copy array + val.0 = (); + } +} + +struct Wrap(T); +struct NonCopy(()); + +impl Deref for Wrap { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for Wrap { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +fn main() {} diff --git a/tests/ui/borrowck/deref-index-pattern-ref-suggestion.rs b/tests/ui/borrowck/deref-index-pattern-ref-suggestion.rs new file mode 100644 index 0000000000000..5cfb2297418ea --- /dev/null +++ b/tests/ui/borrowck/deref-index-pattern-ref-suggestion.rs @@ -0,0 +1,37 @@ +//@ run-rustfix +#![allow(dead_code)] + +use std::ops::{Deref, DerefMut}; + +fn take(mut wrap: Wrap<[Option; 1]>) { + if let Some(mut val) = wrap[0] { + //~^ ERROR cannot move out of type `[Option; 1]`, a non-copy array + val.0 = (); + } +} + +fn take_mut_ref_base(mut wrap: Wrap<[Option; 1]>) { + if let Some(mut val) = (&mut wrap)[0] { + //~^ ERROR cannot move out of type `[Option; 1]`, a non-copy array + val.0 = (); + } +} + +struct Wrap(T); +struct NonCopy(()); + +impl Deref for Wrap { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for Wrap { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +fn main() {} diff --git a/tests/ui/borrowck/deref-index-pattern-ref-suggestion.stderr b/tests/ui/borrowck/deref-index-pattern-ref-suggestion.stderr new file mode 100644 index 0000000000000..fbaf6596bb6e4 --- /dev/null +++ b/tests/ui/borrowck/deref-index-pattern-ref-suggestion.stderr @@ -0,0 +1,29 @@ +error[E0508]: cannot move out of type `[Option; 1]`, a non-copy array + --> $DIR/deref-index-pattern-ref-suggestion.rs:7:28 + | +LL | if let Some(mut val) = wrap[0] { + | ------- ^^^^^^^ cannot move out of here + | | + | data moved here because `val` has type `NonCopy`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | if let Some(ref mut val) = wrap[0] { + | +++ + +error[E0508]: cannot move out of type `[Option; 1]`, a non-copy array + --> $DIR/deref-index-pattern-ref-suggestion.rs:14:28 + | +LL | if let Some(mut val) = (&mut wrap)[0] { + | ------- ^^^^^^^^^^^^^^ cannot move out of here + | | + | data moved here because `val` has type `NonCopy`, which does not implement the `Copy` trait + | +help: consider borrowing the pattern binding + | +LL | if let Some(ref mut val) = (&mut wrap)[0] { + | +++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0508`. diff --git a/tests/ui/moves/moves-based-on-type-block-bad.fixed b/tests/ui/moves/moves-based-on-type-block-bad.fixed new file mode 100644 index 0000000000000..c272203c7f0bf --- /dev/null +++ b/tests/ui/moves/moves-based-on-type-block-bad.fixed @@ -0,0 +1,31 @@ +//@ run-rustfix +#![feature(box_patterns)] +#![allow(dead_code)] + + +struct S { + x: Box +} + +enum E { + Foo(Box), + Bar(Box), + Baz +} + +fn f(s: &S, g: G) where G: FnOnce(&S) { + g(s) +} + +fn main() { + let s = S { x: Box::new(E::Bar(Box::new(42))) }; + loop { + f(&s, |hellothere| { + match hellothere.x { //~ ERROR cannot move out + box E::Foo(_) => {} + box E::Bar(ref x) => println!("{}", x.to_string()), + box E::Baz => {} + } + }) + } +} diff --git a/tests/ui/moves/moves-based-on-type-block-bad.rs b/tests/ui/moves/moves-based-on-type-block-bad.rs index eca33167f454a..e036e10fb180a 100644 --- a/tests/ui/moves/moves-based-on-type-block-bad.rs +++ b/tests/ui/moves/moves-based-on-type-block-bad.rs @@ -1,4 +1,6 @@ +//@ run-rustfix #![feature(box_patterns)] +#![allow(dead_code)] struct S { diff --git a/tests/ui/moves/moves-based-on-type-block-bad.stderr b/tests/ui/moves/moves-based-on-type-block-bad.stderr index 31417b59f0993..8e93b62fa8c65 100644 --- a/tests/ui/moves/moves-based-on-type-block-bad.stderr +++ b/tests/ui/moves/moves-based-on-type-block-bad.stderr @@ -1,5 +1,5 @@ error[E0507]: cannot move out of `hellothere.x` as enum variant `Bar` which is behind a shared reference - --> $DIR/moves-based-on-type-block-bad.rs:22:19 + --> $DIR/moves-based-on-type-block-bad.rs:24:19 | LL | match hellothere.x { | ^^^^^^^^^^^^ @@ -7,10 +7,10 @@ LL | box E::Foo(_) => {} LL | box E::Bar(x) => println!("{}", x.to_string()), | - data moved here because `x` has type `Box`, which does not implement the `Copy` trait | -help: consider borrowing here +help: consider borrowing the pattern binding | -LL | match &hellothere.x { - | + +LL | box E::Bar(ref x) => println!("{}", x.to_string()), + | +++ error: aborting due to 1 previous error diff --git a/tests/ui/nll/move-errors.stderr b/tests/ui/nll/move-errors.stderr index c1ec357cab069..ea186fdc5aa20 100644 --- a/tests/ui/nll/move-errors.stderr +++ b/tests/ui/nll/move-errors.stderr @@ -156,10 +156,14 @@ LL | B::V(s) => (), | - ...and here | = note: move occurs because these variables have types that don't implement the `Copy` trait -help: consider borrowing here +help: consider borrowing the pattern binding + | +LL | B::U(ref d) => (), + | +++ +help: consider borrowing the pattern binding | -LL | match &x[0] { - | + +LL | B::V(ref s) => (), + | +++ error[E0509]: cannot move out of type `D`, which implements the `Drop` trait --> $DIR/move-errors.rs:83:11 diff --git a/tests/ui/pattern/mut-pattern-of-immutable-borrow.stderr b/tests/ui/pattern/mut-pattern-of-immutable-borrow.stderr index f9ef1efa6b2e5..afbf67f203a5a 100644 --- a/tests/ui/pattern/mut-pattern-of-immutable-borrow.stderr +++ b/tests/ui/pattern/mut-pattern-of-immutable-borrow.stderr @@ -6,10 +6,10 @@ LL | match arg.field { LL | Some(s) => s.push('a'), | - data moved here because `s` has type `String`, which does not implement the `Copy` trait | -help: consider borrowing here +help: consider borrowing the pattern binding | -LL | match &arg.field { - | + +LL | Some(ref s) => s.push('a'), + | +++ error[E0596]: cannot borrow `s` as mutable, as it is not declared as mutable --> $DIR/mut-pattern-of-immutable-borrow.rs:7:20 diff --git a/tests/ui/suggestions/dont-suggest-ref/simple.rs b/tests/ui/suggestions/dont-suggest-ref/simple.rs index 4dea5319264ed..07f2dcaa276ce 100644 --- a/tests/ui/suggestions/dont-suggest-ref/simple.rs +++ b/tests/ui/suggestions/dont-suggest-ref/simple.rs @@ -10,6 +10,26 @@ struct X(Y); #[derive(Clone)] struct Y; +struct Wrap(T); + +struct WrappedField { + field: Option, +} + +impl std::ops::Deref for Wrap { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl std::ops::DerefMut for Wrap { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + pub fn main() { let e = Either::One(X(Y)); let mut em = Either::One(X(Y)); @@ -141,6 +161,14 @@ pub fn main() { // FIXME: should suggest removing `ref` too } + let wrapped_field = Wrap(WrappedField { field: Some(X(Y)) }); + if let Some(mut _t) = (&wrapped_field).field { } + //~^ ERROR cannot move + + let wrapped_index = Wrap([Some(X(Y))]); + if let Some(mut _t) = (&wrapped_index)[0] { } + //~^ ERROR cannot move + // move from &Either/&X place let &X(_t) = s; diff --git a/tests/ui/suggestions/dont-suggest-ref/simple.stderr b/tests/ui/suggestions/dont-suggest-ref/simple.stderr index 8e7582fbe588e..b41ebcb3b4e83 100644 --- a/tests/ui/suggestions/dont-suggest-ref/simple.stderr +++ b/tests/ui/suggestions/dont-suggest-ref/simple.stderr @@ -1,5 +1,5 @@ error[E0507]: cannot move out of `s` which is behind a shared reference - --> $DIR/simple.rs:38:17 + --> $DIR/simple.rs:58:17 | LL | let X(_t) = *s; | -- ^^ @@ -13,7 +13,7 @@ LL + let X(_t) = s; | error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference - --> $DIR/simple.rs:41:30 + --> $DIR/simple.rs:61:30 | LL | if let Either::One(_t) = *r { } | -- ^^ @@ -27,7 +27,7 @@ LL + if let Either::One(_t) = r { } | error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference - --> $DIR/simple.rs:44:33 + --> $DIR/simple.rs:64:33 | LL | while let Either::One(_t) = *r { } | -- ^^ @@ -41,7 +41,7 @@ LL + while let Either::One(_t) = r { } | error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference - --> $DIR/simple.rs:47:11 + --> $DIR/simple.rs:67:11 | LL | match *r { | ^^ @@ -56,7 +56,7 @@ LL + match r { | error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference - --> $DIR/simple.rs:53:11 + --> $DIR/simple.rs:73:11 | LL | match *r { | ^^ @@ -71,7 +71,7 @@ LL + match r { | error[E0507]: cannot move out of `sm` which is behind a mutable reference - --> $DIR/simple.rs:61:17 + --> $DIR/simple.rs:81:17 | LL | let X(_t) = *sm; | -- ^^^ @@ -85,7 +85,7 @@ LL + let X(_t) = sm; | error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference - --> $DIR/simple.rs:64:30 + --> $DIR/simple.rs:84:30 | LL | if let Either::One(_t) = *rm { } | -- ^^^ @@ -99,7 +99,7 @@ LL + if let Either::One(_t) = rm { } | error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference - --> $DIR/simple.rs:67:33 + --> $DIR/simple.rs:87:33 | LL | while let Either::One(_t) = *rm { } | -- ^^^ @@ -113,7 +113,7 @@ LL + while let Either::One(_t) = rm { } | error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference - --> $DIR/simple.rs:70:11 + --> $DIR/simple.rs:90:11 | LL | match *rm { | ^^^ @@ -128,7 +128,7 @@ LL + match rm { | error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference - --> $DIR/simple.rs:76:11 + --> $DIR/simple.rs:96:11 | LL | match *rm { | ^^^ @@ -143,7 +143,7 @@ LL + match rm { | error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference - --> $DIR/simple.rs:83:11 + --> $DIR/simple.rs:103:11 | LL | match *rm { | ^^^ @@ -158,7 +158,7 @@ LL + match rm { | error[E0507]: cannot move out of index of `Vec` - --> $DIR/simple.rs:91:17 + --> $DIR/simple.rs:111:17 | LL | let X(_t) = vs[0]; | -- ^^^^^ @@ -171,7 +171,7 @@ LL | let X(_t) = &vs[0]; | + error[E0507]: cannot move out of index of `Vec` - --> $DIR/simple.rs:94:30 + --> $DIR/simple.rs:114:30 | LL | if let Either::One(_t) = vr[0] { } | -- ^^^^^ @@ -184,7 +184,7 @@ LL | if let Either::One(_t) = &vr[0] { } | + error[E0507]: cannot move out of index of `Vec` - --> $DIR/simple.rs:97:33 + --> $DIR/simple.rs:117:33 | LL | while let Either::One(_t) = vr[0] { } | -- ^^^^^ @@ -197,7 +197,7 @@ LL | while let Either::One(_t) = &vr[0] { } | + error[E0507]: cannot move out of index of `Vec` - --> $DIR/simple.rs:100:11 + --> $DIR/simple.rs:120:11 | LL | match vr[0] { | ^^^^^ @@ -211,7 +211,7 @@ LL | match &vr[0] { | + error[E0507]: cannot move out of index of `Vec` - --> $DIR/simple.rs:106:11 + --> $DIR/simple.rs:126:11 | LL | match vr[0] { | ^^^^^ @@ -225,7 +225,7 @@ LL | match &vr[0] { | + error[E0507]: cannot move out of index of `Vec` - --> $DIR/simple.rs:114:17 + --> $DIR/simple.rs:134:17 | LL | let X(_t) = vsm[0]; | -- ^^^^^^ @@ -238,7 +238,7 @@ LL | let X(_t) = &vsm[0]; | + error[E0507]: cannot move out of index of `Vec` - --> $DIR/simple.rs:117:30 + --> $DIR/simple.rs:137:30 | LL | if let Either::One(_t) = vrm[0] { } | -- ^^^^^^ @@ -251,7 +251,7 @@ LL | if let Either::One(_t) = &vrm[0] { } | + error[E0507]: cannot move out of index of `Vec` - --> $DIR/simple.rs:120:33 + --> $DIR/simple.rs:140:33 | LL | while let Either::One(_t) = vrm[0] { } | -- ^^^^^^ @@ -264,7 +264,7 @@ LL | while let Either::One(_t) = &vrm[0] { } | + error[E0507]: cannot move out of index of `Vec` - --> $DIR/simple.rs:123:11 + --> $DIR/simple.rs:143:11 | LL | match vrm[0] { | ^^^^^^ @@ -278,7 +278,7 @@ LL | match &vrm[0] { | + error[E0507]: cannot move out of index of `Vec` - --> $DIR/simple.rs:129:11 + --> $DIR/simple.rs:149:11 | LL | match vrm[0] { | ^^^^^^ @@ -292,7 +292,7 @@ LL | match &vrm[0] { | + error[E0507]: cannot move out of index of `Vec` - --> $DIR/simple.rs:136:11 + --> $DIR/simple.rs:156:11 | LL | match vrm[0] { | ^^^^^^ @@ -305,8 +305,24 @@ help: consider borrowing here LL | match &vrm[0] { | + +error[E0507]: cannot move out of dereference of `Wrap` + --> $DIR/simple.rs:165:27 + | +LL | if let Some(mut _t) = (&wrapped_field).field { } + | ------ ^^^^^^^^^^^^^^^^^^^^^^ + | | + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait + +error[E0508]: cannot move out of type `[Option; 1]`, a non-copy array + --> $DIR/simple.rs:169:27 + | +LL | if let Some(mut _t) = (&wrapped_index)[0] { } + | ------ ^^^^^^^^^^^^^^^^^^^ cannot move out of here + | | + | data moved here because `_t` has type `X`, which does not implement the `Copy` trait + error[E0507]: cannot move out of `s` which is behind a shared reference - --> $DIR/simple.rs:146:18 + --> $DIR/simple.rs:174:18 | LL | let &X(_t) = s; | -- ^ @@ -320,7 +336,7 @@ LL + let X(_t) = s; | error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference - --> $DIR/simple.rs:149:31 + --> $DIR/simple.rs:177:31 | LL | if let &Either::One(_t) = r { } | -- ^ @@ -334,7 +350,7 @@ LL + if let Either::One(_t) = r { } | error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference - --> $DIR/simple.rs:152:34 + --> $DIR/simple.rs:180:34 | LL | while let &Either::One(_t) = r { } | -- ^ @@ -348,7 +364,7 @@ LL + while let Either::One(_t) = r { } | error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference - --> $DIR/simple.rs:155:11 + --> $DIR/simple.rs:183:11 | LL | match r { | ^ @@ -363,7 +379,7 @@ LL + Either::One(_t) | error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference - --> $DIR/simple.rs:162:11 + --> $DIR/simple.rs:190:11 | LL | match r { | ^ @@ -378,7 +394,7 @@ LL + Either::One(_t) => (), | error[E0507]: cannot move out of `r` as enum variant `One` which is behind a shared reference - --> $DIR/simple.rs:168:11 + --> $DIR/simple.rs:196:11 | LL | match r { | ^ @@ -393,7 +409,7 @@ LL + Either::One(_t) => (), | error[E0507]: cannot move out of `sm` which is behind a mutable reference - --> $DIR/simple.rs:178:22 + --> $DIR/simple.rs:206:22 | LL | let &mut X(_t) = sm; | -- ^^ @@ -407,7 +423,7 @@ LL + let X(_t) = sm; | error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference - --> $DIR/simple.rs:181:35 + --> $DIR/simple.rs:209:35 | LL | if let &mut Either::One(_t) = rm { } | -- ^^ @@ -421,7 +437,7 @@ LL + if let Either::One(_t) = rm { } | error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference - --> $DIR/simple.rs:184:38 + --> $DIR/simple.rs:212:38 | LL | while let &mut Either::One(_t) = rm { } | -- ^^ @@ -435,7 +451,7 @@ LL + while let Either::One(_t) = rm { } | error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference - --> $DIR/simple.rs:187:11 + --> $DIR/simple.rs:215:11 | LL | match rm { | ^^ @@ -459,7 +475,7 @@ LL + Either::Two(_t) => (), | error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference - --> $DIR/simple.rs:194:11 + --> $DIR/simple.rs:222:11 | LL | match rm { | ^^ @@ -474,7 +490,7 @@ LL + Either::One(_t) => (), | error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference - --> $DIR/simple.rs:200:11 + --> $DIR/simple.rs:228:11 | LL | match rm { | ^^ @@ -489,7 +505,7 @@ LL + Either::One(_t) => (), | error[E0507]: cannot move out of `rm` as enum variant `One` which is behind a mutable reference - --> $DIR/simple.rs:206:11 + --> $DIR/simple.rs:234:11 | LL | match rm { | ^^ @@ -504,7 +520,7 @@ LL + Either::One(_t) => (), | error[E0507]: cannot move out of a shared reference - --> $DIR/simple.rs:220:21 + --> $DIR/simple.rs:248:21 | LL | let (&X(_t),) = (&x.clone(),); | -- ^^^^^^^^^^^^^ @@ -518,7 +534,7 @@ LL + let (X(_t),) = (&x.clone(),); | error[E0507]: cannot move out of a shared reference - --> $DIR/simple.rs:223:34 + --> $DIR/simple.rs:251:34 | LL | if let (&Either::One(_t),) = (&e.clone(),) { } | -- ^^^^^^^^^^^^^ @@ -532,7 +548,7 @@ LL + if let (Either::One(_t),) = (&e.clone(),) { } | error[E0507]: cannot move out of a shared reference - --> $DIR/simple.rs:226:37 + --> $DIR/simple.rs:254:37 | LL | while let (&Either::One(_t),) = (&e.clone(),) { } | -- ^^^^^^^^^^^^^ @@ -546,7 +562,7 @@ LL + while let (Either::One(_t),) = (&e.clone(),) { } | error[E0507]: cannot move out of a shared reference - --> $DIR/simple.rs:229:11 + --> $DIR/simple.rs:257:11 | LL | match (&e.clone(),) { | ^^^^^^^^^^^^^ @@ -561,7 +577,7 @@ LL + (Either::One(_t),) | error[E0507]: cannot move out of a mutable reference - --> $DIR/simple.rs:239:25 + --> $DIR/simple.rs:267:25 | LL | let (&mut X(_t),) = (&mut xm.clone(),); | -- ^^^^^^^^^^^^^^^^^^ @@ -575,7 +591,7 @@ LL + let (X(_t),) = (&mut xm.clone(),); | error[E0507]: cannot move out of a mutable reference - --> $DIR/simple.rs:242:38 + --> $DIR/simple.rs:270:38 | LL | if let (&mut Either::One(_t),) = (&mut em.clone(),) { } | -- ^^^^^^^^^^^^^^^^^^ @@ -589,7 +605,7 @@ LL + if let (Either::One(_t),) = (&mut em.clone(),) { } | error[E0507]: cannot move out of a mutable reference - --> $DIR/simple.rs:245:41 + --> $DIR/simple.rs:273:41 | LL | while let (&mut Either::One(_t),) = (&mut em.clone(),) { } | -- ^^^^^^^^^^^^^^^^^^ @@ -603,7 +619,7 @@ LL + while let (Either::One(_t),) = (&mut em.clone(),) { } | error[E0507]: cannot move out of a mutable reference - --> $DIR/simple.rs:248:11 + --> $DIR/simple.rs:276:11 | LL | match (&mut em.clone(),) { | ^^^^^^^^^^^^^^^^^^ @@ -627,7 +643,7 @@ LL + (Either::Two(_t),) => (), | error[E0507]: cannot move out of a shared reference - --> $DIR/simple.rs:261:18 + --> $DIR/simple.rs:289:18 | LL | let &X(_t) = &x; | -- ^^ @@ -641,7 +657,7 @@ LL + let X(_t) = &x; | error[E0507]: cannot move out of a shared reference - --> $DIR/simple.rs:264:31 + --> $DIR/simple.rs:292:31 | LL | if let &Either::One(_t) = &e { } | -- ^^ @@ -655,7 +671,7 @@ LL + if let Either::One(_t) = &e { } | error[E0507]: cannot move out of a shared reference - --> $DIR/simple.rs:267:34 + --> $DIR/simple.rs:295:34 | LL | while let &Either::One(_t) = &e { } | -- ^^ @@ -669,7 +685,7 @@ LL + while let Either::One(_t) = &e { } | error[E0507]: cannot move out of a shared reference - --> $DIR/simple.rs:270:11 + --> $DIR/simple.rs:298:11 | LL | match &e { | ^^ @@ -684,7 +700,7 @@ LL + Either::One(_t) | error[E0507]: cannot move out of a shared reference - --> $DIR/simple.rs:277:11 + --> $DIR/simple.rs:305:11 | LL | match &e { | ^^ @@ -699,7 +715,7 @@ LL + Either::One(_t) => (), | error[E0507]: cannot move out of a shared reference - --> $DIR/simple.rs:283:11 + --> $DIR/simple.rs:311:11 | LL | match &e { | ^^ @@ -714,7 +730,7 @@ LL + Either::One(_t) => (), | error[E0507]: cannot move out of a mutable reference - --> $DIR/simple.rs:290:22 + --> $DIR/simple.rs:318:22 | LL | let &mut X(_t) = &mut xm; | -- ^^^^^^^ @@ -728,7 +744,7 @@ LL + let X(_t) = &mut xm; | error[E0507]: cannot move out of a mutable reference - --> $DIR/simple.rs:293:35 + --> $DIR/simple.rs:321:35 | LL | if let &mut Either::One(_t) = &mut em { } | -- ^^^^^^^ @@ -742,7 +758,7 @@ LL + if let Either::One(_t) = &mut em { } | error[E0507]: cannot move out of a mutable reference - --> $DIR/simple.rs:296:38 + --> $DIR/simple.rs:324:38 | LL | while let &mut Either::One(_t) = &mut em { } | -- ^^^^^^^ @@ -756,7 +772,7 @@ LL + while let Either::One(_t) = &mut em { } | error[E0507]: cannot move out of a mutable reference - --> $DIR/simple.rs:299:11 + --> $DIR/simple.rs:327:11 | LL | match &mut em { | ^^^^^^^ @@ -771,7 +787,7 @@ LL + Either::One(_t) | error[E0507]: cannot move out of a mutable reference - --> $DIR/simple.rs:306:11 + --> $DIR/simple.rs:334:11 | LL | match &mut em { | ^^^^^^^ @@ -786,7 +802,7 @@ LL + Either::One(_t) => (), | error[E0507]: cannot move out of a mutable reference - --> $DIR/simple.rs:312:11 + --> $DIR/simple.rs:340:11 | LL | match &mut em { | ^^^^^^^ @@ -801,7 +817,7 @@ LL + Either::One(_t) => (), | error[E0507]: cannot move out of a mutable reference - --> $DIR/simple.rs:318:11 + --> $DIR/simple.rs:346:11 | LL | match &mut em { | ^^^^^^^ @@ -816,7 +832,7 @@ LL + Either::One(_t) => (), | error[E0507]: cannot move out of a shared reference - --> $DIR/simple.rs:174:11 + --> $DIR/simple.rs:202:11 | LL | fn f1(&X(_t): &X) { } | ^^^--^ @@ -830,7 +846,7 @@ LL + fn f1(X(_t): &X) { } | error[E0507]: cannot move out of a mutable reference - --> $DIR/simple.rs:212:11 + --> $DIR/simple.rs:240:11 | LL | fn f2(&mut X(_t): &mut X) { } | ^^^^^^^--^ @@ -844,7 +860,7 @@ LL + fn f2(X(_t): &mut X) { } | error[E0507]: cannot move out of a shared reference - --> $DIR/simple.rs:235:11 + --> $DIR/simple.rs:263:11 | LL | fn f3((&X(_t),): (&X,)) { } | ^^^^--^^^ @@ -858,7 +874,7 @@ LL + fn f3((X(_t),): (&X,)) { } | error[E0507]: cannot move out of a mutable reference - --> $DIR/simple.rs:255:11 + --> $DIR/simple.rs:283:11 | LL | fn f4((&mut X(_t),): (&mut X,)) { } | ^^^^^^^^--^^^ @@ -872,7 +888,7 @@ LL + fn f4((X(_t),): (&mut X,)) { } | error[E0507]: cannot move out of `a.a` as enum variant `Some` which is behind a shared reference - --> $DIR/simple.rs:331:20 + --> $DIR/simple.rs:359:20 | LL | let Some(_s) = a.a else { | -- ^^^ @@ -884,6 +900,7 @@ help: consider borrowing the pattern binding LL | let Some(ref _s) = a.a else { | +++ -error: aborting due to 61 previous errors +error: aborting due to 63 previous errors -For more information about this error, try `rustc --explain E0507`. +Some errors have detailed explanations: E0507, E0508. +For more information about an error, try `rustc --explain E0507`.