diff --git a/src/librustc_error_codes/error_codes/E0009.md b/src/librustc_error_codes/error_codes/E0009.md index abb7fe41ab7a2..aaabba0434993 100644 --- a/src/librustc_error_codes/error_codes/E0009.md +++ b/src/librustc_error_codes/error_codes/E0009.md @@ -1,3 +1,5 @@ +#### Note: this error code is no longer emitted by the compiler. + In a pattern, all values that don't implement the `Copy` trait have to be bound the same way. The goal here is to avoid binding simultaneously by-move and by-ref. @@ -6,7 +8,9 @@ This limitation may be removed in a future version of Rust. Erroneous code example: -```compile_fail,E0009 +``` +#![feature(move_ref_pattern)] + struct X { x: (), } let x = Some((X { x: () }, X { x: () })); diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index 3c217c1d64373..82bbae18a9c0b 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -186,11 +186,25 @@ impl<'a> DiagnosticBuilder<'a> { /// all, and you just supplied a `Span` to create the diagnostic, /// then the snippet will just include that `Span`, which is /// called the primary span. - pub fn span_label>(&mut self, span: Span, label: T) -> &mut Self { + pub fn span_label(&mut self, span: Span, label: impl Into) -> &mut Self { self.0.diagnostic.span_label(span, label); self } + /// Labels all the given spans with the provided label. + /// See `span_label` for more information. + pub fn span_labels( + &mut self, + spans: impl IntoIterator, + label: impl AsRef, + ) -> &mut Self { + let label = label.as_ref(); + for span in spans { + self.0.diagnostic.span_label(span, label); + } + self + } + forward!(pub fn note_expected_found( &mut self, expected_label: &dyn fmt::Display, diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index f20a57ea61c42..e0abf5d4f3c1f 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -538,6 +538,10 @@ declare_features! ( /// For example, you can write `x @ Some(y)`. (active, bindings_after_at, "1.41.0", Some(65490), None), + /// Allows patterns with concurrent by-move and by-ref bindings. + /// For example, you can write `Foo(a, ref b)` where `a` is by-move and `b` is by-ref. + (active, move_ref_pattern, "1.42.0", Some(68354), None), + /// Allows `impl const Trait for T` syntax. (active, const_trait_impl, "1.42.0", Some(67792), None), diff --git a/src/librustc_mir_build/hair/pattern/check_match.rs b/src/librustc_mir_build/hair/pattern/check_match.rs index 82822f0c471a4..b77bd4ecb8e1f 100644 --- a/src/librustc_mir_build/hair/pattern/check_match.rs +++ b/src/librustc_mir_build/hair/pattern/check_match.rs @@ -16,8 +16,7 @@ use rustc_session::lint::builtin::BINDINGS_WITH_VARIANT_NAME; use rustc_session::lint::builtin::{IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS}; use rustc_session::parse::feature_err; use rustc_session::Session; -use rustc_span::symbol::sym; -use rustc_span::{MultiSpan, Span}; +use rustc_span::{sym, Span}; use syntax::ast::Mutability; use std::slice; @@ -114,8 +113,10 @@ impl PatCtxt<'_, '_> { impl<'tcx> MatchVisitor<'_, 'tcx> { fn check_patterns(&mut self, has_guard: bool, pat: &Pat<'_>) { - check_legality_of_move_bindings(self, has_guard, pat); - check_borrow_conflicts_in_at_patterns(self, pat); + if !self.tcx.features().move_ref_pattern { + check_legality_of_move_bindings(self, has_guard, pat); + } + pat.walk_always(|pat| check_borrow_conflicts_in_at_patterns(self, pat)); if !self.tcx.features().bindings_after_at { check_legality_of_bindings_in_at_patterns(self, pat); } @@ -559,6 +560,11 @@ fn maybe_point_at_variant(ty: Ty<'_>, patterns: &[super::Pat<'_>]) -> Vec covered } +/// Check if a by-value binding is by-value. That is, check if the binding's type is not `Copy`. +fn is_binding_by_move(cx: &MatchVisitor<'_, '_>, hir_id: HirId, span: Span) -> bool { + !cx.tables.node_type(hir_id).is_copy_modulo_regions(cx.tcx, cx.param_env, span) +} + /// Check the legality of legality of by-move bindings. fn check_legality_of_move_bindings(cx: &mut MatchVisitor<'_, '_>, has_guard: bool, pat: &Pat<'_>) { let sess = cx.tcx.sess; @@ -589,8 +595,7 @@ fn check_legality_of_move_bindings(cx: &mut MatchVisitor<'_, '_>, has_guard: boo pat.walk_always(|p| { if let hir::PatKind::Binding(.., sub) = &p.kind { if let Some(ty::BindByValue(_)) = tables.extract_binding_mode(sess, p.hir_id, p.span) { - let pat_ty = tables.node_type(p.hir_id); - if !pat_ty.is_copy_modulo_regions(cx.tcx, cx.param_env, pat.span) { + if is_binding_by_move(cx, p.hir_id, p.span) { check_move(p, sub.as_deref()); } } @@ -599,11 +604,11 @@ fn check_legality_of_move_bindings(cx: &mut MatchVisitor<'_, '_>, has_guard: boo // Found some bad by-move spans, error! if !by_move_spans.is_empty() { - let mut err = struct_span_err!( - sess, - MultiSpan::from_spans(by_move_spans.clone()), - E0009, - "cannot bind by-move and by-ref in the same pattern", + let mut err = feature_err( + &sess.parse_sess, + sym::move_ref_pattern, + by_move_spans.clone(), + "binding by-move and by-ref in the same pattern is unstable", ); for span in by_ref_spans.iter() { err.span_label(*span, "by-ref pattern here"); @@ -615,81 +620,118 @@ fn check_legality_of_move_bindings(cx: &mut MatchVisitor<'_, '_>, has_guard: boo } } -/// Check that there are no borrow conflicts in `binding @ subpat` patterns. +/// Check that there are no borrow or move conflicts in `binding @ subpat` patterns. /// /// For example, this would reject: /// - `ref x @ Some(ref mut y)`, -/// - `ref mut x @ Some(ref y)` -/// - `ref mut x @ Some(ref mut y)`. +/// - `ref mut x @ Some(ref y)`, +/// - `ref mut x @ Some(ref mut y)`, +/// - `ref mut? x @ Some(y)`, and +/// - `x @ Some(ref mut? y)`. /// /// This analysis is *not* subsumed by NLL. fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_>, pat: &Pat<'_>) { - let tab = cx.tables; - let sess = cx.tcx.sess; - // Get the mutability of `p` if it's by-ref. - let extract_binding_mut = |hir_id, span| match tab.extract_binding_mode(sess, hir_id, span)? { - ty::BindByValue(_) => None, - ty::BindByReference(m) => Some(m), + // Extract `sub` in `binding @ sub`. + let (name, sub) = match &pat.kind { + hir::PatKind::Binding(.., name, Some(sub)) => (*name, sub), + _ => return, }; - pat.walk_always(|pat| { - // Extract `sub` in `binding @ sub`. - let (name, sub) = match &pat.kind { - hir::PatKind::Binding(.., name, Some(sub)) => (*name, sub), - _ => return, - }; + let binding_span = pat.span.with_hi(name.span.hi()); - // Extract the mutability. - let mut_outer = match extract_binding_mut(pat.hir_id, pat.span) { - None => return, - Some(m) => m, - }; + let tables = cx.tables; + let sess = cx.tcx.sess; - // We now have `ref $mut_outer binding @ sub` (semantically). - // Recurse into each binding in `sub` and find mutability conflicts. - let mut conflicts_mut_mut = Vec::new(); - let mut conflicts_mut_ref = Vec::new(); - sub.each_binding(|_, hir_id, span, _| { - if let Some(mut_inner) = extract_binding_mut(hir_id, span) { - match (mut_outer, mut_inner) { - (Mutability::Not, Mutability::Not) => {} - (Mutability::Mut, Mutability::Mut) => conflicts_mut_mut.push(span), - _ => conflicts_mut_ref.push(span), + // Get the binding move, extract the mutability if by-ref. + let mut_outer = match tables.extract_binding_mode(sess, pat.hir_id, pat.span) { + Some(ty::BindByValue(_)) if is_binding_by_move(cx, pat.hir_id, pat.span) => { + // We have `x @ pat` where `x` is by-move. Reject all borrows in `pat`. + let mut conflicts_ref = Vec::new(); + sub.each_binding(|_, hir_id, span, _| { + match tables.extract_binding_mode(sess, hir_id, span) { + Some(ty::BindByValue(_)) | None => {} + Some(ty::BindByReference(_)) => conflicts_ref.push(span), } + }); + if !conflicts_ref.is_empty() { + let occurs_because = format!( + "move occurs because `{}` has type `{}` which does implement the `Copy` trait", + name, + tables.node_type(pat.hir_id), + ); + sess.struct_span_err(pat.span, "borrow of moved value") + .span_label(binding_span, format!("value moved into `{}` here", name)) + .span_label(binding_span, occurs_because) + .span_labels(conflicts_ref, "value borrowed here after move") + .emit(); } - }); + return; + } + Some(ty::BindByValue(_)) | None => return, + Some(ty::BindByReference(m)) => m, + }; - // Report errors if any. - let binding_span = pat.span.with_hi(name.span.hi()); - if !conflicts_mut_mut.is_empty() { - // Report mutability conflicts for e.g. `ref mut x @ Some(ref mut y)`. - let msg = &format!("cannot borrow `{}` as mutable more than once at a time", name); - let mut err = sess.struct_span_err(pat.span, msg); - err.span_label(binding_span, "first mutable borrow occurs here"); - for sp in conflicts_mut_mut { - err.span_label(sp, "another mutable borrow occurs here"); - } - for sp in conflicts_mut_ref { - err.span_label(sp, "also borrowed as immutable here"); - } - err.emit(); - } else if !conflicts_mut_ref.is_empty() { - // Report mutability conflicts for e.g. `ref x @ Some(ref mut y)` or the converse. - let (primary, also) = match mut_outer { - Mutability::Mut => ("mutable", "immutable"), - Mutability::Not => ("immutable", "mutable"), - }; - let msg = &format!( - "cannot borrow `{}` as {} because it is also borrowed as {}", - name, also, primary, - ); - let mut err = sess.struct_span_err(pat.span, msg); - err.span_label(binding_span, &format!("{} borrow occurs here", primary)); - for sp in conflicts_mut_ref { - err.span_label(sp, &format!("{} borrow occurs here", also)); + // We now have `ref $mut_outer binding @ sub` (semantically). + // Recurse into each binding in `sub` and find mutability or move conflicts. + let mut conflicts_move = Vec::new(); + let mut conflicts_mut_mut = Vec::new(); + let mut conflicts_mut_ref = Vec::new(); + sub.each_binding(|_, hir_id, span, name| { + match tables.extract_binding_mode(sess, hir_id, span) { + Some(ty::BindByReference(mut_inner)) => match (mut_outer, mut_inner) { + (Mutability::Not, Mutability::Not) => {} // Both sides are `ref`. + (Mutability::Mut, Mutability::Mut) => conflicts_mut_mut.push((span, name)), // 2x `ref mut`. + _ => conflicts_mut_ref.push((span, name)), // `ref` + `ref mut` in either direction. + }, + Some(ty::BindByValue(_)) if is_binding_by_move(cx, hir_id, span) => { + conflicts_move.push((span, name)) // `ref mut?` + by-move conflict. } - err.emit(); + Some(ty::BindByValue(_)) | None => {} // `ref mut?` + by-copy is fine. } }); + + // Report errors if any. + if !conflicts_mut_mut.is_empty() { + // Report mutability conflicts for e.g. `ref mut x @ Some(ref mut y)`. + let mut err = sess + .struct_span_err(pat.span, "cannot borrow value as mutable more than once at a time"); + err.span_label(binding_span, format!("first mutable borrow, by `{}`, occurs here", name)); + for (span, name) in conflicts_mut_mut { + err.span_label(span, format!("another mutable borrow, by `{}`, occurs here", name)); + } + for (span, name) in conflicts_mut_ref { + err.span_label(span, format!("also borrowed as immutable, by `{}`, here", name)); + } + for (span, name) in conflicts_move { + err.span_label(span, format!("also moved into `{}` here", name)); + } + err.emit(); + } else if !conflicts_mut_ref.is_empty() { + // Report mutability conflicts for e.g. `ref x @ Some(ref mut y)` or the converse. + let (primary, also) = match mut_outer { + Mutability::Mut => ("mutable", "immutable"), + Mutability::Not => ("immutable", "mutable"), + }; + let msg = + format!("cannot borrow value as {} because it is also borrowed as {}", also, primary); + let mut err = sess.struct_span_err(pat.span, &msg); + err.span_label(binding_span, format!("{} borrow, by `{}`, occurs here", primary, name)); + for (span, name) in conflicts_mut_ref { + err.span_label(span, format!("{} borrow, by `{}`, occurs here", also, name)); + } + for (span, name) in conflicts_move { + err.span_label(span, format!("also moved into `{}` here", name)); + } + err.emit(); + } else if !conflicts_move.is_empty() { + // Report by-ref and by-move conflicts, e.g. `ref x @ y`. + let mut err = + sess.struct_span_err(pat.span, "cannot move out of value because it is borrowed"); + err.span_label(binding_span, format!("value borrowed, by `{}`, here", name)); + for (span, name) in conflicts_move { + err.span_label(span, format!("value moved into `{}` here", name)); + } + err.emit(); + } } /// Forbids bindings in `@` patterns. This used to be is necessary for memory safety, diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index e4f8b5a014389..a8cd027831d31 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -455,6 +455,7 @@ symbols! { module, module_path, more_struct_aliases, + move_ref_pattern, move_val_init, movbe_target_feature, mul_with_overflow, diff --git a/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-2.rs b/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-2.rs deleted file mode 100644 index 238f2d958c625..0000000000000 --- a/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-2.rs +++ /dev/null @@ -1,15 +0,0 @@ -struct X { x: (), } - -impl Drop for X { - fn drop(&mut self) { - println!("destructor runs"); - } -} - -fn main() { - let x = Some((X { x: () }, X { x: () })); - match x { - Some((ref _y, _z)) => { }, //~ ERROR cannot bind by-move and by-ref in the same pattern - None => panic!() - } -} diff --git a/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-2.stderr b/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-2.stderr deleted file mode 100644 index ff00aa8caa8d3..0000000000000 --- a/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-2.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0009]: cannot bind by-move and by-ref in the same pattern - --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-2.rs:12:23 - | -LL | Some((ref _y, _z)) => { }, - | ------ ^^ by-move pattern here - | | - | by-ref pattern here - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0009`. diff --git a/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-3.rs b/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-3.rs deleted file mode 100644 index e8357e9178819..0000000000000 --- a/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-3.rs +++ /dev/null @@ -1,18 +0,0 @@ -struct X { x: (), } - -impl Drop for X { - fn drop(&mut self) { - println!("destructor runs"); - } -} - -enum DoubleOption { Some2(T,U), None2 } - -fn main() { - let x = DoubleOption::Some2(X { x: () }, X { x: () }); - match x { - DoubleOption::Some2(ref _y, _z) => { }, - //~^ ERROR cannot bind by-move and by-ref in the same pattern - DoubleOption::None2 => panic!() - } -} diff --git a/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-3.stderr b/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-3.stderr deleted file mode 100644 index 3e8358da3507d..0000000000000 --- a/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-3.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0009]: cannot bind by-move and by-ref in the same pattern - --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-3.rs:14:37 - | -LL | DoubleOption::Some2(ref _y, _z) => { }, - | ------ ^^ by-move pattern here - | | - | by-ref pattern here - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0009`. diff --git a/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-4.rs b/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-4.rs deleted file mode 100644 index 41dafd2b5bf72..0000000000000 --- a/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-4.rs +++ /dev/null @@ -1,15 +0,0 @@ -struct X { x: (), } - -impl Drop for X { - fn drop(&mut self) { - println!("destructor runs"); - } -} - -fn main() { - let x = Some((X { x: () }, X { x: () })); - match x { - Some((_y, ref _z)) => { }, //~ ERROR cannot bind by-move and by-ref in the same pattern - None => panic!() - } -} diff --git a/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-4.stderr b/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-4.stderr deleted file mode 100644 index 00e0c70d6494b..0000000000000 --- a/src/test/ui/bind-by-move/bind-by-move-neither-can-live-while-the-other-survives-4.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0009]: cannot bind by-move and by-ref in the same pattern - --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-4.rs:12:15 - | -LL | Some((_y, ref _z)) => { }, - | ^^ ------ by-ref pattern here - | | - | by-move pattern here - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0009`. diff --git a/src/test/ui/drop/dynamic-drop-async.rs b/src/test/ui/drop/dynamic-drop-async.rs index 30a8960594493..88d36ab6aa664 100644 --- a/src/test/ui/drop/dynamic-drop-async.rs +++ b/src/test/ui/drop/dynamic-drop-async.rs @@ -7,6 +7,8 @@ // edition:2018 // ignore-wasm32-bare compiled with panic=abort by default +#![feature(move_ref_pattern)] + #![allow(unused)] use std::{ @@ -227,6 +229,12 @@ async fn subslice_pattern_reassign(a: Rc) { a.alloc().await; } +async fn move_ref_pattern(a: Rc) { + let mut tup = (a.alloc().await, a.alloc().await, a.alloc().await, a.alloc().await); + let (ref _a, ref mut _b, _c, mut _d) = tup; + a.alloc().await; +} + fn run_test(cx: &mut Context<'_>, ref f: F) where F: Fn(Rc) -> G, @@ -322,4 +330,6 @@ fn main() { run_test(context, |a| subslice_pattern_from_end_with_drop(a, false, true)); run_test(context, |a| subslice_pattern_from_end_with_drop(a, false, false)); run_test(context, |a| subslice_pattern_reassign(a)); + + run_test(context, |a| move_ref_pattern(a)); } diff --git a/src/test/ui/drop/dynamic-drop.rs b/src/test/ui/drop/dynamic-drop.rs index b4406204a5db9..208a743ed1815 100644 --- a/src/test/ui/drop/dynamic-drop.rs +++ b/src/test/ui/drop/dynamic-drop.rs @@ -2,6 +2,7 @@ // ignore-wasm32-bare compiled with panic=abort by default #![feature(generators, generator_trait, untagged_unions)] +#![feature(move_ref_pattern)] #![allow(unused_assignments)] #![allow(unused_variables)] @@ -290,6 +291,11 @@ fn subslice_mixed_min_lengths(a: &Allocator, c: i32) { } } +fn move_ref_pattern(a: &Allocator) { + let mut tup = (a.alloc(), a.alloc(), a.alloc(), a.alloc()); + let (ref _a, ref mut _b, _c, mut _d) = tup; +} + fn panic_after_return(a: &Allocator) -> Ptr<'_> { // Panic in the drop of `p` or `q` can leak let exceptions = vec![8, 9]; @@ -453,6 +459,8 @@ fn main() { run_test(|a| subslice_mixed_min_lengths(a, 6)); run_test(|a| subslice_mixed_min_lengths(a, 7)); + run_test(|a| move_ref_pattern(a)); + run_test(|a| { panic_after_return(a); }); diff --git a/src/test/ui/error-codes/E0009.rs b/src/test/ui/error-codes/E0009.rs deleted file mode 100644 index 0610d03cfe96d..0000000000000 --- a/src/test/ui/error-codes/E0009.rs +++ /dev/null @@ -1,9 +0,0 @@ -fn main() { - struct X { x: (), } - let x = Some((X { x: () }, X { x: () })); - match x { - Some((y, ref z)) => {}, - //~^ ERROR E0009 - None => panic!() - } -} diff --git a/src/test/ui/error-codes/E0009.stderr b/src/test/ui/error-codes/E0009.stderr deleted file mode 100644 index 446a436d64779..0000000000000 --- a/src/test/ui/error-codes/E0009.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0009]: cannot bind by-move and by-ref in the same pattern - --> $DIR/E0009.rs:5:15 - | -LL | Some((y, ref z)) => {}, - | ^ ----- by-ref pattern here - | | - | by-move pattern here - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0009`. diff --git a/src/test/ui/issues/issue-53840.stderr b/src/test/ui/issues/issue-53840.stderr deleted file mode 100644 index 9cb034e7592da..0000000000000 --- a/src/test/ui/issues/issue-53840.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0009]: cannot bind by-move and by-ref in the same pattern - --> $DIR/issue-53840.rs:13:16 - | -LL | E::Foo(a, b, ref c) => {} - | ^ ^ ----- by-ref pattern here - | | | - | | by-move pattern here - | by-move pattern here - -error[E0009]: cannot bind by-move and by-ref in the same pattern - --> $DIR/issue-53840.rs:17:14 - | -LL | Bar {a, ref b} => {} - | ^ ----- by-ref pattern here - | | - | by-move pattern here - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0009`. 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 e460246193e5b..5c1a61eb375a4 100644 --- a/src/test/ui/moves/move-out-of-slice-2.rs +++ b/src/test/ui/moves/move-out-of-slice-2.rs @@ -1,4 +1,4 @@ -#![feature(slice_patterns, unsized_locals)] +#![feature(unsized_locals)] struct A; #[derive(Clone, Copy)] diff --git a/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.rs b/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.rs index 75d7af58e706d..c00296c34c4e5 100644 --- a/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.rs +++ b/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.rs @@ -3,33 +3,38 @@ // where one side is by-ref and the other is by-move. #![feature(bindings_after_at)] +#![feature(move_ref_pattern)] -struct X { x: () } +struct X { + x: (), +} fn main() { let x = Some(X { x: () }); match x { - Some(ref _y @ _z) => { }, //~ ERROR cannot bind by-move and by-ref in the same pattern - None => panic!() + Some(ref _y @ _z) => {} //~ ERROR cannot move out of value because it is borrowed + None => panic!(), } let x = Some(X { x: () }); match x { - Some(_z @ ref _y) => { }, //~ ERROR cannot bind by-move with sub-bindings + Some(_z @ ref _y) => {} //~^ ERROR borrow of moved value - None => panic!() + //~| ERROR borrow of moved value + None => panic!(), } let mut x = Some(X { x: () }); match x { - Some(ref mut _y @ _z) => { }, //~ ERROR cannot bind by-move and by-ref in the same pattern - None => panic!() + Some(ref mut _y @ _z) => {} //~ ERROR cannot move out of value because it is borrowed + None => panic!(), } let mut x = Some(X { x: () }); match x { - Some(_z @ ref mut _y) => { }, //~ ERROR cannot bind by-move with sub-bindings + Some(_z @ ref mut _y) => {} //~^ ERROR borrow of moved value - None => panic!() + //~| ERROR borrow of moved value + None => panic!(), } } diff --git a/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr b/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr index 22d62ff4f003f..026747c212a2c 100644 --- a/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr +++ b/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr @@ -1,37 +1,45 @@ -error[E0009]: cannot bind by-move and by-ref in the same pattern - --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:12:23 +error: cannot move out of value because it is borrowed + --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:15:14 | -LL | Some(ref _y @ _z) => { }, - | ---------^^ +LL | Some(ref _y @ _z) => {} + | ------^^^-- | | | - | | by-move pattern here - | by-ref pattern here + | | value moved into `_z` here + | value borrowed, by `_y`, here -error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:18:14 +error: borrow of moved value + --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:21:14 | -LL | Some(_z @ ref _y) => { }, - | ^^^^^^^^^^^ binds an already bound by-move value by moving it +LL | Some(_z @ ref _y) => {} + | --^^^------ + | | | + | | value borrowed here after move + | value moved into `_z` here + | move occurs because `_z` has type `X` which does implement the `Copy` trait -error[E0009]: cannot bind by-move and by-ref in the same pattern - --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:25:27 +error: cannot move out of value because it is borrowed + --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:29:14 | -LL | Some(ref mut _y @ _z) => { }, - | -------------^^ +LL | Some(ref mut _y @ _z) => {} + | ----------^^^-- | | | - | | by-move pattern here - | by-ref pattern here + | | value moved into `_z` here + | value borrowed, by `_y`, here -error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:31:14 +error: borrow of moved value + --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:35:14 | -LL | Some(_z @ ref mut _y) => { }, - | ^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it +LL | Some(_z @ ref mut _y) => {} + | --^^^---------- + | | | + | | value borrowed here after move + | value moved into `_z` here + | move occurs because `_z` has type `X` which does implement the `Copy` trait error[E0382]: borrow of moved value - --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:18:19 + --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:21:19 | -LL | Some(_z @ ref _y) => { }, +LL | Some(_z @ ref _y) => {} | -----^^^^^^ | | | | | value borrowed here after move @@ -40,9 +48,9 @@ LL | Some(_z @ ref _y) => { }, = note: move occurs because value has type `X`, which does not implement the `Copy` trait error[E0382]: borrow of moved value - --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:31:19 + --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:35:19 | -LL | Some(_z @ ref mut _y) => { }, +LL | Some(_z @ ref mut _y) => {} | -----^^^^^^^^^^ | | | | | value borrowed here after move @@ -52,5 +60,4 @@ LL | Some(_z @ ref mut _y) => { }, error: aborting due to 6 previous errors -Some errors have detailed explanations: E0007, E0009, E0382. -For more information about an error, try `rustc --explain E0007`. +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.rs b/src/test/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.rs index 86fb04e2edf5b..7a2e5128b8537 100644 --- a/src/test/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.rs +++ b/src/test/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.rs @@ -1,14 +1,14 @@ // See issue #12534. #![feature(bindings_after_at)] +#![feature(move_ref_pattern)] fn main() {} struct A(Box); fn f(a @ A(u): A) -> Box { - //~^ ERROR cannot bind by-move with sub-bindings - //~| ERROR use of moved value + //~^ ERROR use of moved value drop(a); u } diff --git a/src/test/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.stderr b/src/test/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.stderr index b039708fd3e0a..cfd978e132709 100644 --- a/src/test/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.stderr +++ b/src/test/ui/pattern/bindings-after-at/bind-by-move-no-subbindings-fun-param.stderr @@ -1,11 +1,5 @@ -error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/bind-by-move-no-subbindings-fun-param.rs:9:6 - | -LL | fn f(a @ A(u): A) -> Box { - | ^^^^^^^^ binds an already bound by-move value by moving it - error[E0382]: use of moved value - --> $DIR/bind-by-move-no-subbindings-fun-param.rs:9:12 + --> $DIR/bind-by-move-no-subbindings-fun-param.rs:10:12 | LL | fn f(a @ A(u): A) -> Box { | ------^- @@ -14,7 +8,6 @@ LL | fn f(a @ A(u): A) -> Box { | value moved here | move occurs because value has type `A`, which does not implement the `Copy` trait -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0007, E0382. -For more information about an error, try `rustc --explain E0007`. +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.rs b/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.rs index 2cd375da9a56f..10865b92393b6 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.rs +++ b/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.rs @@ -1,46 +1,34 @@ // Test that moving on both sides of an `@` pattern is not allowed. #![feature(bindings_after_at)] +#![feature(move_ref_pattern)] fn main() { struct U; // Not copy! // Prevent promotion: - fn u() -> U { U } + fn u() -> U { + U + } - let a @ b = U; - //~^ ERROR cannot bind by-move with sub-bindings - //~| ERROR use of moved value + let a @ b = U; //~ ERROR use of moved value - let a @ (b, c) = (U, U); - //~^ ERROR cannot bind by-move with sub-bindings - //~| ERROR use of moved value + let a @ (b, c) = (U, U); //~ ERROR use of moved value - let a @ (b, c) = (u(), u()); - //~^ ERROR cannot bind by-move with sub-bindings - //~| ERROR use of moved value + let a @ (b, c) = (u(), u()); //~ ERROR use of moved value match Ok(U) { - a @ Ok(b) | a @ Err(b) => {} - //~^ ERROR cannot bind by-move with sub-bindings - //~| ERROR use of moved value - //~| ERROR cannot bind by-move with sub-bindings - //~| ERROR use of moved value + a @ Ok(b) | a @ Err(b) => {} //~ ERROR use of moved value + //~^ ERROR use of moved value } - fn fun(a @ b: U) {} - //~^ ERROR cannot bind by-move with sub-bindings - //~| ERROR use of moved value + fn fun(a @ b: U) {} //~ ERROR use of moved value match [u(), u(), u(), u()] { - xs @ [a, .., b] => {} - //~^ ERROR cannot bind by-move with sub-bindings - //~| ERROR use of moved value + xs @ [a, .., b] => {} //~ ERROR use of moved value } match [u(), u(), u(), u()] { - xs @ [_, ys @ .., _] => {} - //~^ ERROR cannot bind by-move with sub-bindings - //~| ERROR use of moved value + xs @ [_, ys @ .., _] => {} //~ ERROR use of moved value } } diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr index 12ebcb72af11c..56613ee7618b4 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr +++ b/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr @@ -1,53 +1,5 @@ -error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/borrowck-move-and-move.rs:11:9 - | -LL | let a @ b = U; - | ^^^^^ binds an already bound by-move value by moving it - -error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/borrowck-move-and-move.rs:15:9 - | -LL | let a @ (b, c) = (U, U); - | ^^^^^^^^^^ binds an already bound by-move value by moving it - -error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/borrowck-move-and-move.rs:19:9 - | -LL | let a @ (b, c) = (u(), u()); - | ^^^^^^^^^^ binds an already bound by-move value by moving it - -error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/borrowck-move-and-move.rs:24:9 - | -LL | a @ Ok(b) | a @ Err(b) => {} - | ^^^^^^^^^ binds an already bound by-move value by moving it - -error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/borrowck-move-and-move.rs:24:21 - | -LL | a @ Ok(b) | a @ Err(b) => {} - | ^^^^^^^^^^ binds an already bound by-move value by moving it - -error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/borrowck-move-and-move.rs:36:9 - | -LL | xs @ [a, .., b] => {} - | ^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it - -error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/borrowck-move-and-move.rs:42:9 - | -LL | xs @ [_, ys @ .., _] => {} - | ^^^^^^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it - -error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/borrowck-move-and-move.rs:31:12 - | -LL | fn fun(a @ b: U) {} - | ^^^^^ binds an already bound by-move value by moving it - error[E0382]: use of moved value - --> $DIR/borrowck-move-and-move.rs:11:13 + --> $DIR/borrowck-move-and-move.rs:14:13 | LL | let a @ b = U; | ----^ - move occurs because value has type `main::U`, which does not implement the `Copy` trait @@ -56,7 +8,7 @@ LL | let a @ b = U; | value moved here error[E0382]: use of moved value - --> $DIR/borrowck-move-and-move.rs:15:17 + --> $DIR/borrowck-move-and-move.rs:16:17 | LL | let a @ (b, c) = (U, U); | --------^- ------ move occurs because value has type `(main::U, main::U)`, which does not implement the `Copy` trait @@ -65,7 +17,7 @@ LL | let a @ (b, c) = (U, U); | value moved here error[E0382]: use of moved value - --> $DIR/borrowck-move-and-move.rs:19:17 + --> $DIR/borrowck-move-and-move.rs:18:17 | LL | let a @ (b, c) = (u(), u()); | --------^- ---------- move occurs because value has type `(main::U, main::U)`, which does not implement the `Copy` trait @@ -74,7 +26,7 @@ LL | let a @ (b, c) = (u(), u()); | value moved here error[E0382]: use of moved value - --> $DIR/borrowck-move-and-move.rs:24:16 + --> $DIR/borrowck-move-and-move.rs:21:16 | LL | match Ok(U) { | ----- move occurs because value has type `std::result::Result`, which does not implement the `Copy` trait @@ -85,7 +37,7 @@ LL | a @ Ok(b) | a @ Err(b) => {} | value moved here error[E0382]: use of moved value - --> $DIR/borrowck-move-and-move.rs:24:29 + --> $DIR/borrowck-move-and-move.rs:21:29 | LL | match Ok(U) { | ----- move occurs because value has type `std::result::Result`, which does not implement the `Copy` trait @@ -96,7 +48,7 @@ LL | a @ Ok(b) | a @ Err(b) => {} | value moved here error[E0382]: use of moved value - --> $DIR/borrowck-move-and-move.rs:36:22 + --> $DIR/borrowck-move-and-move.rs:28:22 | LL | match [u(), u(), u(), u()] { | -------------------- move occurs because value has type `[main::U; 4]`, which does not implement the `Copy` trait @@ -107,7 +59,7 @@ LL | xs @ [a, .., b] => {} | value moved here error[E0382]: use of moved value - --> $DIR/borrowck-move-and-move.rs:42:18 + --> $DIR/borrowck-move-and-move.rs:32:18 | LL | match [u(), u(), u(), u()] { | -------------------- move occurs because value has type `[main::U; 4]`, which does not implement the `Copy` trait @@ -118,7 +70,7 @@ LL | xs @ [_, ys @ .., _] => {} | value moved here error[E0382]: use of moved value - --> $DIR/borrowck-move-and-move.rs:31:16 + --> $DIR/borrowck-move-and-move.rs:25:16 | LL | fn fun(a @ b: U) {} | ----^ @@ -127,7 +79,6 @@ LL | fn fun(a @ b: U) {} | value moved here | move occurs because value has type `main::U`, which does not implement the `Copy` trait -error: aborting due to 16 previous errors +error: aborting due to 8 previous errors -Some errors have detailed explanations: E0007, E0382. -For more information about an error, try `rustc --explain E0007`. +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs index 092bd1133dd62..271f4bca0fcb8 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs @@ -3,6 +3,7 @@ // Test `@` patterns combined with `box` patterns. #![feature(bindings_after_at)] +#![feature(move_ref_pattern)] #![feature(box_patterns)] #[derive(Copy, Clone)] @@ -72,4 +73,14 @@ fn main() { } _ => {} } + + match Box::new([Ok(c()), Err(nc()), Ok(c())]) { + box [Ok(a), ref xs @ .., Err(b)] => {} + _ => {} + } + + match [Ok(Box::new(c())), Err(Box::new(nc())), Ok(Box::new(c())), Ok(Box::new(c()))] { + [Ok(box ref a), ref xs @ .., Err(box b), Err(box ref mut c)] => {} + _ => {} + } } diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs index 3b2f598dc0157..32c638bcbcca3 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs @@ -1,61 +1,62 @@ // Test `@` patterns combined with `box` patterns. #![feature(bindings_after_at)] +#![feature(move_ref_pattern)] #![feature(box_patterns)] #[derive(Copy, Clone)] struct C; -fn c() -> C { C } +fn c() -> C { + C +} struct NC; -fn nc() -> NC { NC } +fn nc() -> NC { + NC +} fn main() { let a @ box &b = Box::new(&C); - //~^ ERROR cannot bind by-move with sub-bindings - //~| ERROR use of moved value + //~^ ERROR use of moved value let a @ box b = Box::new(C); - //~^ ERROR cannot bind by-move with sub-bindings - //~| ERROR use of moved value + //~^ ERROR use of moved value fn f1(a @ box &b: Box<&C>) {} - //~^ ERROR cannot bind by-move with sub-bindings - //~| ERROR use of moved value + //~^ ERROR use of moved value fn f2(a @ box b: Box) {} - //~^ ERROR cannot bind by-move with sub-bindings - //~| ERROR use of moved value + //~^ ERROR use of moved value - match Box::new(C) { a @ box b => {} } - //~^ ERROR cannot bind by-move with sub-bindings - //~| ERROR use of moved value + match Box::new(C) { + a @ box b => {} //~ ERROR use of moved value + } - let ref a @ box b = Box::new(NC); //~ ERROR cannot bind by-move and by-ref in the same pattern + let ref a @ box b = Box::new(NC); //~ ERROR cannot move out of value because it is borrowed let ref a @ box ref mut b = Box::new(nc()); - //~^ ERROR cannot borrow `a` as mutable because it is also borrowed as immutable + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable let ref a @ box ref mut b = Box::new(NC); - //~^ ERROR cannot borrow `a` as mutable because it is also borrowed as immutable + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable let ref a @ box ref mut b = Box::new(NC); - //~^ ERROR cannot borrow `a` as mutable because it is also borrowed as immutable + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable *b = NC; let ref a @ box ref mut b = Box::new(NC); - //~^ ERROR cannot borrow `a` as mutable because it is also borrowed as immutable + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable //~| ERROR cannot borrow `_` as mutable because it is also borrowed as immutable *b = NC; drop(a); let ref mut a @ box ref b = Box::new(NC); - //~^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable //~| ERROR cannot borrow `_` as immutable because it is also borrowed as mutable *a = Box::new(NC); drop(b); fn f5(ref mut a @ box ref b: Box) { - //~^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable //~| ERROR cannot borrow `_` as immutable because it is also borrowed as mutable *a = Box::new(NC); drop(b); @@ -63,22 +64,10 @@ fn main() { match Box::new(nc()) { ref mut a @ box ref b => { - //~^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable //~| ERROR cannot borrow `_` as immutable because it is also borrowed as mutable *a = Box::new(NC); drop(b); } } - - match Box::new([Ok(c()), Err(nc()), Ok(c())]) { - box [Ok(a), ref xs @ .., Err(b)] => {} - //~^ ERROR cannot bind by-move and by-ref in the same pattern - _ => {} - } - - match [Ok(Box::new(c())), Err(Box::new(nc())), Ok(Box::new(c())), Ok(Box::new(c()))] { - [Ok(box ref a), ref xs @ .., Err(box b), Err(box ref mut c)] => {} - //~^ ERROR cannot bind by-move and by-ref in the same pattern - _ => {} - } } diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr index e96c15b0fa7dd..5534d0a75e63d 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr @@ -1,125 +1,77 @@ -error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/borrowck-pat-at-and-box.rs:16:9 - | -LL | let a @ box &b = Box::new(&C); - | ^^^^^^^^^^ binds an already bound by-move value by moving it - -error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/borrowck-pat-at-and-box.rs:20:9 - | -LL | let a @ box b = Box::new(C); - | ^^^^^^^^^ binds an already bound by-move value by moving it - -error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/borrowck-pat-at-and-box.rs:32:25 - | -LL | match Box::new(C) { a @ box b => {} } - | ^^^^^^^^^ binds an already bound by-move value by moving it - -error[E0009]: cannot bind by-move and by-ref in the same pattern - --> $DIR/borrowck-pat-at-and-box.rs:36:21 +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-at-and-box.rs:37:9 | LL | let ref a @ box b = Box::new(NC); - | ------------^ + | -----^^^^^^^- | | | - | | by-move pattern here - | by-ref pattern here + | | value moved into `b` here + | value borrowed, by `a`, here -error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-at-and-box.rs:38:9 +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-at-and-box.rs:39:9 | LL | let ref a @ box ref mut b = Box::new(nc()); | -----^^^^^^^--------- | | | - | | mutable borrow occurs here - | immutable borrow occurs here + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here -error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-at-and-box.rs:40:9 +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-at-and-box.rs:41:9 | LL | let ref a @ box ref mut b = Box::new(NC); | -----^^^^^^^--------- | | | - | | mutable borrow occurs here - | immutable borrow occurs here + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here -error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-at-and-box.rs:42:9 +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-at-and-box.rs:43:9 | LL | let ref a @ box ref mut b = Box::new(NC); | -----^^^^^^^--------- | | | - | | mutable borrow occurs here - | immutable borrow occurs here + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here -error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-at-and-box.rs:45:9 +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-at-and-box.rs:46:9 | LL | let ref a @ box ref mut b = Box::new(NC); | -----^^^^^^^--------- | | | - | | mutable borrow occurs here - | immutable borrow occurs here + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here -error: cannot borrow `a` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-at-and-box.rs:51:9 +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-at-and-box.rs:52:9 | LL | let ref mut a @ box ref b = Box::new(NC); | ---------^^^^^^^----- | | | - | | immutable borrow occurs here - | mutable borrow occurs here + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here -error: cannot borrow `a` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-at-and-box.rs:65:9 +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-at-and-box.rs:66:9 | LL | ref mut a @ box ref b => { | ---------^^^^^^^----- | | | - | | immutable borrow occurs here - | mutable borrow occurs here - -error[E0009]: cannot bind by-move and by-ref in the same pattern - --> $DIR/borrowck-pat-at-and-box.rs:74:38 - | -LL | box [Ok(a), ref xs @ .., Err(b)] => {} - | ----------- ^ by-move pattern here - | | - | by-ref pattern here - -error[E0009]: cannot bind by-move and by-ref in the same pattern - --> $DIR/borrowck-pat-at-and-box.rs:80:46 - | -LL | [Ok(box ref a), ref xs @ .., Err(box b), Err(box ref mut c)] => {} - | ----- ----------- ^ --------- by-ref pattern here - | | | | - | | | by-move pattern here - | | by-ref pattern here - | by-ref pattern here - -error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/borrowck-pat-at-and-box.rs:24:11 - | -LL | fn f1(a @ box &b: Box<&C>) {} - | ^^^^^^^^^^ binds an already bound by-move value by moving it + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here -error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/borrowck-pat-at-and-box.rs:28:11 - | -LL | fn f2(a @ box b: Box) {} - | ^^^^^^^^^ binds an already bound by-move value by moving it - -error: cannot borrow `a` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-at-and-box.rs:57:11 +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-at-and-box.rs:58:11 | LL | fn f5(ref mut a @ box ref b: Box) { | ---------^^^^^^^----- | | | - | | immutable borrow occurs here - | mutable borrow occurs here + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here error[E0382]: use of moved value - --> $DIR/borrowck-pat-at-and-box.rs:16:18 + --> $DIR/borrowck-pat-at-and-box.rs:21:18 | LL | let a @ box &b = Box::new(&C); | ---------^ ------------ move occurs because value has type `std::boxed::Box<&C>`, which does not implement the `Copy` trait @@ -128,7 +80,7 @@ LL | let a @ box &b = Box::new(&C); | value moved here error[E0382]: use of moved value - --> $DIR/borrowck-pat-at-and-box.rs:20:17 + --> $DIR/borrowck-pat-at-and-box.rs:24:17 | LL | let a @ box b = Box::new(C); | --------^ ----------- move occurs because value has type `std::boxed::Box`, which does not implement the `Copy` trait @@ -137,17 +89,18 @@ LL | let a @ box b = Box::new(C); | value moved here error[E0382]: use of moved value - --> $DIR/borrowck-pat-at-and-box.rs:32:33 + --> $DIR/borrowck-pat-at-and-box.rs:34:17 | -LL | match Box::new(C) { a @ box b => {} } - | ----------- --------^ - | | | | - | | | value used here after move - | | value moved here - | move occurs because value has type `std::boxed::Box`, which does not implement the `Copy` trait +LL | match Box::new(C) { + | ----------- move occurs because value has type `std::boxed::Box`, which does not implement the `Copy` trait +LL | a @ box b => {} + | --------^ + | | | + | | value used here after move + | value moved here error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-at-and-box.rs:45:21 + --> $DIR/borrowck-pat-at-and-box.rs:46:21 | LL | let ref a @ box ref mut b = Box::new(NC); | ------------^^^^^^^^^ @@ -159,7 +112,7 @@ LL | drop(a); | - immutable borrow later used here error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-at-and-box.rs:51:25 + --> $DIR/borrowck-pat-at-and-box.rs:52:25 | LL | let ref mut a @ box ref b = Box::new(NC); | ----------------^^^^^ @@ -171,7 +124,7 @@ LL | *a = Box::new(NC); | -- mutable borrow later used here error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-at-and-box.rs:65:25 + --> $DIR/borrowck-pat-at-and-box.rs:66:25 | LL | ref mut a @ box ref b => { | ----------------^^^^^ @@ -183,7 +136,7 @@ LL | *a = Box::new(NC); | -- mutable borrow later used here error[E0382]: use of moved value - --> $DIR/borrowck-pat-at-and-box.rs:24:20 + --> $DIR/borrowck-pat-at-and-box.rs:27:20 | LL | fn f1(a @ box &b: Box<&C>) {} | ---------^ @@ -193,7 +146,7 @@ LL | fn f1(a @ box &b: Box<&C>) {} | move occurs because value has type `std::boxed::Box<&C>`, which does not implement the `Copy` trait error[E0382]: use of moved value - --> $DIR/borrowck-pat-at-and-box.rs:28:19 + --> $DIR/borrowck-pat-at-and-box.rs:30:19 | LL | fn f2(a @ box b: Box) {} | --------^ @@ -203,7 +156,7 @@ LL | fn f2(a @ box b: Box) {} | move occurs because value has type `std::boxed::Box`, which does not implement the `Copy` trait error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-at-and-box.rs:57:27 + --> $DIR/borrowck-pat-at-and-box.rs:58:27 | LL | fn f5(ref mut a @ box ref b: Box) { | ----------------^^^^^ @@ -214,7 +167,7 @@ LL | fn f5(ref mut a @ box ref b: Box) { LL | *a = Box::new(NC); | -- mutable borrow later used here -error: aborting due to 24 previous errors +error: aborting due to 17 previous errors -Some errors have detailed explanations: E0007, E0009, E0382, E0502. -For more information about an error, try `rustc --explain E0007`. +Some errors have detailed explanations: E0382, E0502. +For more information about an error, try `rustc --explain E0382`. diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.rs new file mode 100644 index 0000000000000..1479791719313 --- /dev/null +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.rs @@ -0,0 +1,10 @@ +// Test that `by_move_binding @ pat_with_by_ref_bindings` is prevented even with promotion. +// Currently this logic exists in HAIR match checking as opposed to borrowck. + +#![feature(bindings_after_at)] +#![feature(move_ref_pattern)] + +fn main() { + struct U; + let a @ ref b = U; //~ ERROR borrow of moved value +} diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr new file mode 100644 index 0000000000000..91fdfd4f2abcc --- /dev/null +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr @@ -0,0 +1,12 @@ +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse-promotion.rs:9:9 + | +LL | let a @ ref b = U; + | -^^^----- + | | | + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `main::U` which does implement the `Copy` trait + +error: aborting due to previous error + diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.rs new file mode 100644 index 0000000000000..7d9618c8df78d --- /dev/null +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.rs @@ -0,0 +1,98 @@ +// Test that `by_move_binding @ pat_with_by_ref_bindings` is prevented. + +#![feature(bindings_after_at)] +#![feature(move_ref_pattern)] + +fn main() { + struct U; + + // Prevent promotion. + fn u() -> U { + U + } + + fn f1(a @ ref b: U) {} + //~^ ERROR borrow of moved value + //~| ERROR borrow of moved value + + fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {} + //~^ ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR use of moved value + fn f3(a @ [ref mut b, ref c]: [U; 2]) {} + //~^ ERROR borrow of moved value + //~| ERROR borrow of moved value + + let a @ ref b = U; + //~^ ERROR borrow of moved value + let a @ (mut b @ ref mut c, d @ ref e) = (U, U); + //~^ ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR use of moved value + let a @ [ref mut b, ref c] = [U, U]; + //~^ ERROR borrow of moved value + //~| ERROR borrow of moved value + let a @ ref b = u(); + //~^ ERROR borrow of moved value + //~| ERROR borrow of moved value + let a @ (mut b @ ref mut c, d @ ref e) = (u(), u()); + //~^ ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR use of moved value + let a @ [ref mut b, ref c] = [u(), u()]; + //~^ ERROR borrow of moved value + //~| ERROR borrow of moved value + + match Some(U) { + a @ Some(ref b) => {} + //~^ ERROR borrow of moved value + None => {} + } + match Some((U, U)) { + a @ Some((mut b @ ref mut c, d @ ref e)) => {} + //~^ ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR use of moved value + None => {} + } + match Some([U, U]) { + mut a @ Some([ref b, ref mut c]) => {} + //~^ ERROR borrow of moved value + //~| ERROR borrow of moved value + None => {} + } + match Some(u()) { + a @ Some(ref b) => {} + //~^ ERROR borrow of moved value + //~| ERROR borrow of moved value + None => {} + } + match Some((u(), u())) { + a @ Some((mut b @ ref mut c, d @ ref e)) => {} + //~^ ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR borrow of moved value + //~| ERROR use of moved value + None => {} + } + match Some([u(), u()]) { + mut a @ Some([ref b, ref mut c]) => {} + //~^ ERROR borrow of moved value + //~| ERROR borrow of moved value + None => {} + } +} 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 new file mode 100644 index 0000000000000..ec86692dc6962 --- /dev/null +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr @@ -0,0 +1,503 @@ +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:29:9 + | +LL | let a @ ref b = U; + | -^^^----- + | | | + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `main::U` which does implement the `Copy` trait + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:9 + | +LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U); + | -^^^^^^^^^^^^---------^^^^^^-----^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `(main::U, main::U)` which does implement the `Copy` trait + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:14 + | +LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U); + | -----^^^--------- + | | | + | | value borrowed here after move + | value moved into `b` here + | move occurs because `b` has type `main::U` which does implement the `Copy` trait + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:33 + | +LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U); + | -^^^----- + | | | + | | value borrowed here after move + | value moved into `d` here + | move occurs because `d` has type `main::U` which does implement the `Copy` trait + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:38:9 + | +LL | let a @ [ref mut b, ref c] = [U, U]; + | -^^^^---------^^-----^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `[main::U; 2]` which does implement the `Copy` trait + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:41:9 + | +LL | let a @ ref b = u(); + | -^^^----- + | | | + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `main::U` which does implement the `Copy` trait + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:44:9 + | +LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u()); + | -^^^^^^^^^^^^---------^^^^^^-----^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `(main::U, main::U)` which does implement the `Copy` trait + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:44:14 + | +LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u()); + | -----^^^--------- + | | | + | | value borrowed here after move + | value moved into `b` here + | move occurs because `b` has type `main::U` which does implement the `Copy` trait + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:44:33 + | +LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u()); + | -^^^----- + | | | + | | value borrowed here after move + | value moved into `d` here + | move occurs because `d` has type `main::U` which does implement the `Copy` trait + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:51:9 + | +LL | let a @ [ref mut b, ref c] = [u(), u()]; + | -^^^^---------^^-----^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `[main::U; 2]` which does implement the `Copy` trait + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:56:9 + | +LL | a @ Some(ref b) => {} + | -^^^^^^^^-----^ + | | | + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `std::option::Option` which does implement the `Copy` trait + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:9 + | +LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | -^^^^^^^^^^^^^^^^^---------^^^^^^-----^^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `std::option::Option<(main::U, main::U)>` which does implement the `Copy` trait + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:19 + | +LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | -----^^^--------- + | | | + | | value borrowed here after move + | value moved into `b` here + | move occurs because `b` has type `main::U` which does implement the `Copy` trait + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:38 + | +LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | -^^^----- + | | | + | | value borrowed here after move + | value moved into `d` here + | move occurs because `d` has type `main::U` which does implement the `Copy` trait + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:71:9 + | +LL | mut a @ Some([ref b, ref mut c]) => {} + | -----^^^^^^^^^-----^^---------^^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `std::option::Option<[main::U; 2]>` which does implement the `Copy` trait + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:77:9 + | +LL | a @ Some(ref b) => {} + | -^^^^^^^^-----^ + | | | + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `std::option::Option` which does implement the `Copy` trait + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:83:9 + | +LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | -^^^^^^^^^^^^^^^^^---------^^^^^^-----^^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `std::option::Option<(main::U, main::U)>` which does implement the `Copy` trait + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:83:19 + | +LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | -----^^^--------- + | | | + | | value borrowed here after move + | value moved into `b` here + | move occurs because `b` has type `main::U` which does implement the `Copy` trait + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:83:38 + | +LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | -^^^----- + | | | + | | value borrowed here after move + | value moved into `d` here + | move occurs because `d` has type `main::U` which does implement the `Copy` trait + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:93:9 + | +LL | mut a @ Some([ref b, ref mut c]) => {} + | -----^^^^^^^^^-----^^---------^^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `std::option::Option<[main::U; 2]>` which does implement the `Copy` trait + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:11 + | +LL | fn f1(a @ ref b: U) {} + | -^^^----- + | | | + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `main::U` which does implement the `Copy` trait + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:18:11 + | +LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {} + | -----^^^^^^^^-----^^^^^^^^^^-----^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `(main::U, main::U)` which does implement the `Copy` trait + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:18:20 + | +LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {} + | -^^^----- + | | | + | | value borrowed here after move + | value moved into `b` here + | move occurs because `b` has type `main::U` which does implement the `Copy` trait + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:18:31 + | +LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {} + | -----^^^----- + | | | + | | value borrowed here after move + | value moved into `d` here + | move occurs because `d` has type `main::U` which does implement the `Copy` trait + +error: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:25:11 + | +LL | fn f3(a @ [ref mut b, ref c]: [U; 2]) {} + | -^^^^---------^^-----^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `[main::U; 2]` which does implement the `Copy` trait + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:22 + | +LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U); + | --------^^^^^^^^^ + | | | + | | value borrowed here after move + | value moved here + | + = note: move occurs because value has type `main::U`, which does not implement the `Copy` trait + +error[E0382]: use of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:33 + | +LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U); + | ------------------------^^^^^^^^^- ------ move occurs because value has type `(main::U, main::U)`, which does not implement the `Copy` trait + | | | + | | value used here after move + | value moved here + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:37 + | +LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U); + | ----^^^^^ + | | | + | | value borrowed here after move + | value moved here + | + = note: move occurs because value has type `main::U`, which does not implement the `Copy` trait + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:38:25 + | +LL | let a @ [ref mut b, ref c] = [U, U]; + | ----------------^^^^^- ------ move occurs because value has type `[main::U; 2]`, which does not implement the `Copy` trait + | | | + | | value borrowed here after move + | value moved here + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:41:13 + | +LL | let a @ ref b = u(); + | ----^^^^^ --- move occurs because value has type `main::U`, which does not implement the `Copy` trait + | | | + | | value borrowed here after move + | value moved here + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:44:22 + | +LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u()); + | --------^^^^^^^^^ + | | | + | | value borrowed here after move + | value moved here + | + = note: move occurs because value has type `main::U`, which does not implement the `Copy` trait + +error[E0382]: use of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:44:33 + | +LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u()); + | ------------------------^^^^^^^^^- ---------- move occurs because value has type `(main::U, main::U)`, which does not implement the `Copy` trait + | | | + | | value used here after move + | value moved here + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:44:37 + | +LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u()); + | ----^^^^^ + | | | + | | value borrowed here after move + | value moved here + | + = note: move occurs because value has type `main::U`, which does not implement the `Copy` trait + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:51:25 + | +LL | let a @ [ref mut b, ref c] = [u(), u()]; + | ----------------^^^^^- ---------- move occurs because value has type `[main::U; 2]`, which does not implement the `Copy` trait + | | | + | | value borrowed here after move + | value moved here + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:27 + | +LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | --------^^^^^^^^^ + | | | + | | value borrowed here after move + | value moved here + | + = note: move occurs because value has type `main::U`, which does not implement the `Copy` trait + +error[E0382]: use of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:38 + | +LL | match Some((U, U)) { + | ------------ move occurs because value has type `std::option::Option<(main::U, main::U)>`, which does not implement the `Copy` trait +LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | -----------------------------^^^^^^^^^-- + | | | + | | value used here after move + | value moved here + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:42 + | +LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | ----^^^^^ + | | | + | | value borrowed here after move + | value moved here + | + = note: move occurs because value has type `main::U`, which does not implement the `Copy` trait + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:71:30 + | +LL | match Some([U, U]) { + | ------------ move occurs because value has type `std::option::Option<[main::U; 2]>`, which does not implement the `Copy` trait +LL | mut a @ Some([ref b, ref mut c]) => {} + | ---------------------^^^^^^^^^-- + | | | + | | value borrowed here after move + | value moved here + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:77:18 + | +LL | match Some(u()) { + | --------- move occurs because value has type `std::option::Option`, which does not implement the `Copy` trait +LL | a @ Some(ref b) => {} + | ---------^^^^^- + | | | + | | value borrowed here after move + | value moved here + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:83:27 + | +LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | --------^^^^^^^^^ + | | | + | | value borrowed here after move + | value moved here + | + = note: move occurs because value has type `main::U`, which does not implement the `Copy` trait + +error[E0382]: use of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:83:38 + | +LL | match Some((u(), u())) { + | ---------------- move occurs because value has type `std::option::Option<(main::U, main::U)>`, which does not implement the `Copy` trait +LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | -----------------------------^^^^^^^^^-- + | | | + | | value used here after move + | value moved here + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:83:42 + | +LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} + | ----^^^^^ + | | | + | | value borrowed here after move + | value moved here + | + = note: move occurs because value has type `main::U`, which does not implement the `Copy` trait + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:93:30 + | +LL | match Some([u(), u()]) { + | ---------------- move occurs because value has type `std::option::Option<[main::U; 2]>`, which does not implement the `Copy` trait +LL | mut a @ Some([ref b, ref mut c]) => {} + | ---------------------^^^^^^^^^-- + | | | + | | value borrowed here after move + | value moved here + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:15 + | +LL | fn f1(a @ ref b: U) {} + | ----^^^^^ + | | | + | | value borrowed here after move + | value moved here + | move occurs because value has type `main::U`, which does not implement the `Copy` trait + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:18:24 + | +LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {} + | ----^^^^^ + | | | + | | value borrowed here after move + | value moved here + | + = note: move occurs because value has type `main::U`, which does not implement the `Copy` trait + +error[E0382]: use of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:18:31 + | +LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {} + | --------------------^^^^^^^^^^^^^- + | | | + | | value used here after move + | value moved here + | move occurs because value has type `(main::U, main::U)`, which does not implement the `Copy` trait + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:18:39 + | +LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {} + | --------^^^^^ + | | | + | | value borrowed here after move + | value moved here + | + = note: move occurs because value has type `main::U`, which does not implement the `Copy` trait + +error[E0382]: borrow of moved value + --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:25:27 + | +LL | fn f3(a @ [ref mut b, ref c]: [U; 2]) {} + | ----------------^^^^^- + | | | + | | value borrowed here after move + | value moved here + | move occurs because value has type `[main::U; 2]`, which does not implement the `Copy` trait + +error: aborting due to 48 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.rs index abe5ed81b71a2..b7c8c8766c00a 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.rs +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.rs @@ -1,9 +1,74 @@ +// Test that `ref mut? @ pat_with_by_move_bindings` is prevented. + #![feature(bindings_after_at)] +#![feature(move_ref_pattern)] fn main() { - match Some("hi".to_string()) { - ref op_string_ref @ Some(s) => {}, - //~^ ERROR cannot bind by-move and by-ref in the same pattern [E0009] - None => {}, + struct U; + + // Prevent promotion. + fn u() -> U { + U + } + + fn f1(ref a @ b: U) {} + //~^ ERROR cannot move out of value because it is borrowed + fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {} + //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR cannot move out of value because it is borrowed + //~| ERROR cannot move out of value because it is borrowed + fn f3(ref mut a @ [b, mut c]: [U; 2]) {} + //~^ ERROR cannot move out of value because it is borrowed + + let ref a @ b = U; + //~^ ERROR cannot move out of value because it is borrowed + let ref a @ (ref b @ mut c, ref d @ e) = (U, U); + //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR cannot move out of value because it is borrowed + //~| ERROR cannot move out of value because it is borrowed + let ref mut a @ [b, mut c] = [U, U]; + //~^ ERROR cannot move out of value because it is borrowed + let ref a @ b = u(); + //~^ ERROR cannot move out of value because it is borrowed + let ref a @ (ref b @ mut c, ref d @ e) = (u(), u()); + //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR cannot move out of value because it is borrowed + //~| ERROR cannot move out of value because it is borrowed + let ref mut a @ [b, mut c] = [u(), u()]; + //~^ ERROR cannot move out of value because it is borrowed + + match Some(U) { + ref a @ Some(b) => {} + //~^ ERROR cannot move out of value because it is borrowed + None => {} + } + match Some((U, U)) { + ref a @ Some((ref b @ mut c, ref d @ e)) => {} + //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR cannot move out of value because it is borrowed + //~| ERROR cannot move out of value because it is borrowed + None => {} + } + match Some([U, U]) { + ref mut a @ Some([b, mut c]) => {} + //~^ ERROR cannot move out of value because it is borrowed + None => {} + } + match Some(u()) { + ref a @ Some(b) => {} + //~^ ERROR cannot move out of value because it is borrowed + None => {} + } + match Some((u(), u())) { + ref a @ Some((ref b @ mut c, ref d @ e)) => {} + //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR cannot move out of value because it is borrowed + //~| ERROR cannot move out of value because it is borrowed + None => {} + } + match Some([u(), u()]) { + ref mut a @ Some([b, mut c]) => {} + //~^ ERROR cannot move out of value because it is borrowed + None => {} } } diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr index 1f70a6c437e92..e5419efa00b36 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr @@ -1,12 +1,237 @@ -error[E0009]: cannot bind by-move and by-ref in the same pattern - --> $DIR/borrowck-pat-by-move-and-ref.rs:5:34 +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:23:9 | -LL | ref op_string_ref @ Some(s) => {}, - | -------------------------^- - | | | - | | by-move pattern here - | by-ref pattern here +LL | let ref a @ b = U; + | -----^^^- + | | | + | | value moved into `b` here + | value borrowed, by `a`, here -error: aborting due to previous error +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:25:9 + | +LL | let ref a @ (ref b @ mut c, ref d @ e) = (U, U); + | -----^^^^^^^^^^^^-----^^^^^^^^^^-^ + | | | | + | | | value moved into `e` here + | | value moved into `c` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:25:18 + | +LL | let ref a @ (ref b @ mut c, ref d @ e) = (U, U); + | -----^^^----- + | | | + | | value moved into `c` here + | value borrowed, by `b`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:25:33 + | +LL | let ref a @ (ref b @ mut c, ref d @ e) = (U, U); + | -----^^^- + | | | + | | value moved into `e` here + | value borrowed, by `d`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:29:9 + | +LL | let ref mut a @ [b, mut c] = [U, U]; + | ---------^^^^-^^-----^ + | | | | + | | | value moved into `c` here + | | value moved into `b` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:31:9 + | +LL | let ref a @ b = u(); + | -----^^^- + | | | + | | value moved into `b` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:33:9 + | +LL | let ref a @ (ref b @ mut c, ref d @ e) = (u(), u()); + | -----^^^^^^^^^^^^-----^^^^^^^^^^-^ + | | | | + | | | value moved into `e` here + | | value moved into `c` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:33:18 + | +LL | let ref a @ (ref b @ mut c, ref d @ e) = (u(), u()); + | -----^^^----- + | | | + | | value moved into `c` here + | value borrowed, by `b`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:33:33 + | +LL | let ref a @ (ref b @ mut c, ref d @ e) = (u(), u()); + | -----^^^- + | | | + | | value moved into `e` here + | value borrowed, by `d`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:37:9 + | +LL | let ref mut a @ [b, mut c] = [u(), u()]; + | ---------^^^^-^^-----^ + | | | | + | | | value moved into `c` here + | | value moved into `b` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:41:9 + | +LL | ref a @ Some(b) => {} + | -----^^^^^^^^-^ + | | | + | | value moved into `b` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:46:9 + | +LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} + | -----^^^^^^^^^^^^^^^^^-----^^^^^^^^^^-^^ + | | | | + | | | value moved into `e` here + | | value moved into `c` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:46:23 + | +LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} + | -----^^^----- + | | | + | | value moved into `c` here + | value borrowed, by `b`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:46:38 + | +LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} + | -----^^^- + | | | + | | value moved into `e` here + | value borrowed, by `d`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:53:9 + | +LL | ref mut a @ Some([b, mut c]) => {} + | ---------^^^^^^^^^-^^-----^^ + | | | | + | | | value moved into `c` here + | | value moved into `b` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:58:9 + | +LL | ref a @ Some(b) => {} + | -----^^^^^^^^-^ + | | | + | | value moved into `b` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:63:9 + | +LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} + | -----^^^^^^^^^^^^^^^^^-----^^^^^^^^^^-^^ + | | | | + | | | value moved into `e` here + | | value moved into `c` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:63:23 + | +LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} + | -----^^^----- + | | | + | | value moved into `c` here + | value borrowed, by `b`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:63:38 + | +LL | ref a @ Some((ref b @ mut c, ref d @ e)) => {} + | -----^^^- + | | | + | | value moved into `e` here + | value borrowed, by `d`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:70:9 + | +LL | ref mut a @ Some([b, mut c]) => {} + | ---------^^^^^^^^^-^^-----^^ + | | | | + | | | value moved into `c` here + | | value moved into `b` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:14:11 + | +LL | fn f1(ref a @ b: U) {} + | -----^^^- + | | | + | | value moved into `b` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:16:11 + | +LL | fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {} + | -----^^^^^^^^^^^^-----^^^^^^^^^^-^ + | | | | + | | | value moved into `e` here + | | value moved into `c` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:16:20 + | +LL | fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {} + | -----^^^----- + | | | + | | value moved into `c` here + | value borrowed, by `b`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:16:35 + | +LL | fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {} + | -----^^^- + | | | + | | value moved into `e` here + | value borrowed, by `d`, here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-by-move-and-ref.rs:20:11 + | +LL | fn f3(ref mut a @ [b, mut c]: [U; 2]) {} + | ---------^^^^-^^-----^ + | | | | + | | | value moved into `c` here + | | value moved into `b` here + | value borrowed, by `a`, here + +error: aborting due to 25 previous errors -For more information about this error, try `rustc --explain E0009`. diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs index e8510dfa64999..58d4a9b018cee 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs @@ -1,4 +1,5 @@ #![feature(bindings_after_at)] +#![feature(move_ref_pattern)] enum Option { None, @@ -8,7 +9,7 @@ enum Option { fn main() { match &mut Some(1) { ref mut z @ &mut Some(ref a) => { - //~^ ERROR cannot borrow `z` as immutable because it is also borrowed as mutable + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable //~| ERROR cannot borrow `_` as immutable because it is also borrowed as mutable **z = None; println!("{}", *a); @@ -22,49 +23,52 @@ fn main() { fn u() -> U { U } fn f1(ref a @ ref mut b: U) {} - //~^ ERROR cannot borrow `a` as mutable because it is also borrowed as immutable + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable fn f2(ref mut a @ ref b: U) {} - //~^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable fn f3(ref a @ [ref b, ref mut mid @ .., ref c]: [U; 4]) {} - //~^ ERROR cannot borrow `a` as mutable because it is also borrowed as immutable + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + fn f4_also_moved(ref a @ ref mut b @ c: U) {} + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot move out of value because it is borrowed let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub - //~^ ERROR cannot borrow `a` as mutable more than once at a time - //~| ERROR cannot borrow `b` as mutable because it is also borrowed as immutable + //~^ ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable let ref a @ ref mut b = U; - //~^ ERROR cannot borrow `a` as mutable because it is also borrowed as immutable + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable let ref mut a @ ref b = U; - //~^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable let ref a @ (ref mut b, ref mut c) = (U, U); - //~^ ERROR cannot borrow `a` as mutable because it is also borrowed as immutable + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable let ref mut a @ (ref b, ref c) = (U, U); - //~^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable let ref mut a @ ref b = u(); - //~^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable //~| ERROR cannot borrow `_` as immutable because it is also borrowed as mutable *a = u(); drop(b); let ref a @ ref mut b = u(); - //~^ ERROR cannot borrow `a` as mutable because it is also borrowed as immutable + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable //~| ERROR cannot borrow `_` as mutable because it is also borrowed as immutable *b = u(); drop(a); let ref mut a @ ref b = U; - //~^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable *a = U; drop(b); let ref a @ ref mut b = U; - //~^ ERROR cannot borrow `a` as mutable because it is also borrowed as immutable + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable *b = U; drop(a); match Ok(U) { ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => { - //~^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable - //~| ERROR cannot borrow `a` as immutable because it is also borrowed as mutable + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable *a = Err(U); drop(b); } @@ -72,8 +76,8 @@ fn main() { match Ok(U) { ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { - //~^ ERROR cannot borrow `a` as mutable because it is also borrowed as immutable - //~| ERROR cannot borrow `a` as mutable because it is also borrowed as immutable + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable //~| ERROR cannot borrow `_` as mutable because it is also borrowed as immutable //~| ERROR cannot borrow `_` as mutable because it is also borrowed as immutable *b = U; @@ -83,52 +87,52 @@ fn main() { match Ok(U) { ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {} - //~^ ERROR cannot borrow `a` as mutable because it is also borrowed as immutable - //~| ERROR cannot borrow `a` as mutable because it is also borrowed as immutable + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable //~| ERROR cannot assign to `*b`, as it is immutable for the pattern guard _ => {} } match Ok(U) { ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {} - //~^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable - //~| ERROR cannot borrow `a` as immutable because it is also borrowed as mutable + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable //~| ERROR cannot assign to `*a`, as it is immutable for the pattern guard _ => {} } match Ok(U) { ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} - //~^ ERROR cannot borrow `a` as mutable because it is also borrowed as immutable - //~| ERROR cannot borrow `a` as mutable because it is also borrowed as immutable + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable + //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable //~| ERROR cannot move out of `b` in pattern guard //~| ERROR cannot move out of `b` in pattern guard _ => {} } match Ok(U) { ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} - //~^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable - //~| ERROR cannot borrow `a` as immutable because it is also borrowed as mutable + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable + //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable //~| ERROR cannot move out of `a` in pattern guard //~| ERROR cannot move out of `a` in pattern guard _ => {} } let ref a @ (ref mut b, ref mut c) = (U, U); - //~^ ERROR cannot borrow `a` as mutable because it is also borrowed as immutable + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable *b = U; *c = U; let ref a @ (ref mut b, ref mut c) = (U, U); - //~^ ERROR cannot borrow `a` as mutable because it is also borrowed as immutable + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable //~| ERROR cannot borrow `_` as mutable because it is also borrowed as immutable //~| ERROR cannot borrow `_` as mutable because it is also borrowed as immutable *b = U; drop(a); let ref a @ (ref mut b, ref mut c) = (U, U); - //~^ ERROR cannot borrow `a` as mutable because it is also borrowed as immutable + //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable *b = U; //~| ERROR cannot borrow `_` as mutable because it is also borrowed as immutable *c = U; //~| ERROR cannot borrow `_` as mutable because it is also borrowed as immutable drop(a); let ref mut a @ (ref b, ref c) = (U, U); - //~^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable + //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable } diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr index 0d7b703f1816b..8c6ca888e0762 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr @@ -1,282 +1,301 @@ -error: cannot borrow `z` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:10:9 +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:11:9 | LL | ref mut z @ &mut Some(ref a) => { | ---------^^^^^^^^^^^^^-----^ | | | - | | immutable borrow occurs here - | mutable borrow occurs here + | | immutable borrow, by `a`, occurs here + | mutable borrow, by `z`, occurs here -error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:31:9 +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:35:9 | LL | let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub | ---------^^^^-----------------^ | | | | - | | | another mutable borrow occurs here - | | also borrowed as immutable here - | first mutable borrow occurs here + | | | another mutable borrow, by `c`, occurs here + | | also borrowed as immutable, by `b`, here + | first mutable borrow, by `a`, occurs here -error: cannot borrow `b` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:31:22 +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:35:22 | LL | let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub | -----^^^--------- | | | - | | mutable borrow occurs here - | immutable borrow occurs here + | | mutable borrow, by `c`, occurs here + | immutable borrow, by `b`, occurs here -error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:35:9 +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:39:9 | LL | let ref a @ ref mut b = U; | -----^^^--------- | | | - | | mutable borrow occurs here - | immutable borrow occurs here + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here -error: cannot borrow `a` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:37:9 +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:41:9 | LL | let ref mut a @ ref b = U; | ---------^^^----- | | | - | | immutable borrow occurs here - | mutable borrow occurs here + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here -error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:39:9 +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:43:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | -----^^^^---------^^---------^ | | | | - | | | mutable borrow occurs here - | | mutable borrow occurs here - | immutable borrow occurs here + | | | mutable borrow, by `c`, occurs here + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here -error: cannot borrow `a` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:41:9 +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:45:9 | LL | let ref mut a @ (ref b, ref c) = (U, U); | ---------^^^^-----^^-----^ | | | | - | | | immutable borrow occurs here - | | immutable borrow occurs here - | mutable borrow occurs here + | | | immutable borrow, by `c`, occurs here + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here -error: cannot borrow `a` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:44:9 +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:48:9 | LL | let ref mut a @ ref b = u(); | ---------^^^----- | | | - | | immutable borrow occurs here - | mutable borrow occurs here + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here -error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:49:9 +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:53:9 | LL | let ref a @ ref mut b = u(); | -----^^^--------- | | | - | | mutable borrow occurs here - | immutable borrow occurs here + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here -error: cannot borrow `a` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:55:9 +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:59:9 | LL | let ref mut a @ ref b = U; | ---------^^^----- | | | - | | immutable borrow occurs here - | mutable borrow occurs here + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here -error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:59:9 +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:63:9 | LL | let ref a @ ref mut b = U; | -----^^^--------- | | | - | | mutable borrow occurs here - | immutable borrow occurs here + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here -error: cannot borrow `a` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:65:9 +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:69:9 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => { | ---------^^^^^^-----^ | | | - | | immutable borrow occurs here - | mutable borrow occurs here + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here -error: cannot borrow `a` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:65:33 +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:69:33 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => { | ---------^^^^^^^-----^ | | | - | | immutable borrow occurs here - | mutable borrow occurs here + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here -error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:74:9 +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:78:9 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { | -----^^^^^^---------^ | | | - | | mutable borrow occurs here - | immutable borrow occurs here + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here -error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:74:33 +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:78:33 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { | -----^^^^^^^---------^ | | | - | | mutable borrow occurs here - | immutable borrow occurs here + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here -error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:85:9 +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:89:9 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {} | -----^^^^^^---------^ | | | - | | mutable borrow occurs here - | immutable borrow occurs here + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here -error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:85:33 +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:89:33 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {} | -----^^^^^^^---------^ | | | - | | mutable borrow occurs here - | immutable borrow occurs here + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here -error: cannot borrow `a` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:92:9 +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:96:9 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {} | ---------^^^^^^-----^ | | | - | | immutable borrow occurs here - | mutable borrow occurs here + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here -error: cannot borrow `a` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:92:33 +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:96:33 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {} | ---------^^^^^^^-----^ | | | - | | immutable borrow occurs here - | mutable borrow occurs here + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here -error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:99:9 +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:9 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} | -----^^^^^^---------^ | | | - | | mutable borrow occurs here - | immutable borrow occurs here + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here -error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:99:33 +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:33 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} | -----^^^^^^^---------^ | | | - | | mutable borrow occurs here - | immutable borrow occurs here + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here -error: cannot borrow `a` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:107:9 +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:111:9 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} | ---------^^^^^^-----^ | | | - | | immutable borrow occurs here - | mutable borrow occurs here + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here -error: cannot borrow `a` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:107:33 +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:111:33 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} | ---------^^^^^^^-----^ | | | - | | immutable borrow occurs here - | mutable borrow occurs here + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here -error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:115:9 +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:119:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | -----^^^^---------^^---------^ | | | | - | | | mutable borrow occurs here - | | mutable borrow occurs here - | immutable borrow occurs here + | | | mutable borrow, by `c`, occurs here + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here -error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:120:9 +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:124:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | -----^^^^---------^^---------^ | | | | - | | | mutable borrow occurs here - | | mutable borrow occurs here - | immutable borrow occurs here + | | | mutable borrow, by `c`, occurs here + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here -error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:127:9 +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:131:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | -----^^^^---------^^---------^ | | | | - | | | mutable borrow occurs here - | | mutable borrow occurs here - | immutable borrow occurs here + | | | mutable borrow, by `c`, occurs here + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here -error: cannot borrow `a` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:132:9 +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:136:9 | LL | let ref mut a @ (ref b, ref c) = (U, U); | ---------^^^^-----^^-----^ | | | | - | | | immutable borrow occurs here - | | immutable borrow occurs here - | mutable borrow occurs here + | | | immutable borrow, by `c`, occurs here + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here -error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:24:11 +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:25:11 | LL | fn f1(ref a @ ref mut b: U) {} | -----^^^--------- | | | - | | mutable borrow occurs here - | immutable borrow occurs here + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here -error: cannot borrow `a` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:26:11 +error: cannot borrow value as immutable because it is also borrowed as mutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:27:11 | LL | fn f2(ref mut a @ ref b: U) {} | ---------^^^----- | | | - | | immutable borrow occurs here - | mutable borrow occurs here + | | immutable borrow, by `b`, occurs here + | mutable borrow, by `a`, occurs here -error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:28:11 +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:29:11 | LL | fn f3(ref a @ [ref b, ref mut mid @ .., ref c]: [U; 4]) {} | -----^^^^^^^^^^^----------------^^^^^^^^ | | | - | | mutable borrow occurs here - | immutable borrow occurs here + | | mutable borrow, by `mid`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:31:22 + | +LL | fn f4_also_moved(ref a @ ref mut b @ c: U) {} + | -----^^^------------- + | | | | + | | | also moved into `c` here + | | mutable borrow, by `b`, occurs here + | immutable borrow, by `a`, occurs here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:31:30 + | +LL | fn f4_also_moved(ref a @ ref mut b @ c: U) {} + | ---------^^^- + | | | + | | value moved into `c` here + | value borrowed, by `b`, here error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:10:31 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:11:31 | LL | ref mut z @ &mut Some(ref a) => { | ----------------------^^^^^- @@ -288,7 +307,7 @@ LL | **z = None; | ---------- mutable borrow later used here error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:44:21 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:48:21 | LL | let ref mut a @ ref b = u(); | ------------^^^^^ @@ -300,7 +319,7 @@ LL | *a = u(); | -------- mutable borrow later used here error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:49:17 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:53:17 | LL | let ref a @ ref mut b = u(); | --------^^^^^^^^^ @@ -312,7 +331,7 @@ LL | drop(a); | - immutable borrow later used here error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:74:20 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:78:20 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { | -----------^^^^^^^^^- @@ -324,7 +343,7 @@ LL | drop(a); | - immutable borrow later used here error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:74:45 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:78:45 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { | ------------^^^^^^^^^- @@ -336,7 +355,7 @@ LL | drop(a); | - immutable borrow later used here error[E0594]: cannot assign to `*b`, as it is immutable for the pattern guard - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:85:61 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:89:61 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {} | ^^^^^^ cannot assign @@ -344,7 +363,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } = note: variables bound in patterns are immutable until the end of the pattern guard error[E0594]: cannot assign to `*a`, as it is immutable for the pattern guard - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:92:61 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:96:61 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {} | ^^^^^^^^^^^ cannot assign @@ -352,7 +371,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); fa = note: variables bound in patterns are immutable until the end of the pattern guard error[E0507]: cannot move out of `b` in pattern guard - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:99:66 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:66 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} | ^ move occurs because `b` has type `&mut main::U`, which does not implement the `Copy` trait @@ -360,7 +379,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false = note: variables bound in patterns cannot be moved from until after the end of the pattern guard error[E0507]: cannot move out of `b` in pattern guard - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:99:66 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:66 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} | ^ move occurs because `b` has type `&mut main::U`, which does not implement the `Copy` trait @@ -368,7 +387,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false = note: variables bound in patterns cannot be moved from until after the end of the pattern guard error[E0507]: cannot move out of `a` in pattern guard - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:107:66 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:111:66 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} | ^ move occurs because `a` has type `&mut std::result::Result`, which does not implement the `Copy` trait @@ -376,7 +395,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false = note: variables bound in patterns cannot be moved from until after the end of the pattern guard error[E0507]: cannot move out of `a` in pattern guard - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:107:66 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:111:66 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} | ^ move occurs because `a` has type `&mut std::result::Result`, which does not implement the `Copy` trait @@ -384,7 +403,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false = note: variables bound in patterns cannot be moved from until after the end of the pattern guard error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:120:18 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:124:18 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | ---------^^^^^^^^^------------ @@ -396,7 +415,7 @@ LL | drop(a); | - immutable borrow later used here error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:120:29 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:124:29 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | --------------------^^^^^^^^^- @@ -408,7 +427,7 @@ LL | drop(a); | - immutable borrow later used here error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:127:18 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:131:18 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | ---------^^^^^^^^^------------ @@ -420,7 +439,7 @@ LL | drop(a); | - immutable borrow later used here error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:127:29 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:131:29 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | --------------------^^^^^^^^^- @@ -431,7 +450,7 @@ LL | let ref a @ (ref mut b, ref mut c) = (U, U); LL | drop(a); | - immutable borrow later used here -error: aborting due to 45 previous errors +error: aborting due to 47 previous errors Some errors have detailed explanations: E0502, E0507, E0594. For more information about an error, try `rustc --explain E0502`. diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs index f425b35630d17..f5c39a7ac5276 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs @@ -1,6 +1,7 @@ // Test that `ref mut x @ ref mut y` and varieties of that are not allowed. #![feature(bindings_after_at)] +#![feature(move_ref_pattern)] fn main() { struct U; @@ -8,39 +9,42 @@ fn main() { fn u() -> U { U } fn f1(ref mut a @ ref mut b: U) {} - //~^ ERROR cannot borrow `a` as mutable more than once at a time + //~^ ERROR cannot borrow value as mutable more than once at a time fn f2(ref mut a @ ref mut b: U) {} - //~^ ERROR cannot borrow `a` as mutable more than once at a time + //~^ ERROR cannot borrow value as mutable more than once at a time fn f3( ref mut a @ [ - //~^ ERROR cannot borrow `a` as mutable more than once at a time + //~^ ERROR cannot borrow value as mutable more than once at a time [ref b @ .., _], [_, ref mut mid @ ..], .., [..], ] : [[U; 4]; 5] ) {} + fn f4_also_moved(ref mut a @ ref mut b @ c: U) {} + //~^ ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot move out of value because it is borrowed let ref mut a @ ref mut b = U; - //~^ ERROR cannot borrow `a` as mutable more than once at a time + //~^ ERROR cannot borrow value as mutable more than once at a time //~| ERROR cannot borrow `_` as mutable more than once at a time drop(a); let ref mut a @ ref mut b = U; - //~^ ERROR cannot borrow `a` as mutable more than once at a time + //~^ ERROR cannot borrow value as mutable more than once at a time drop(b); let ref mut a @ ref mut b = U; - //~^ ERROR cannot borrow `a` as mutable more than once at a time + //~^ ERROR cannot borrow value as mutable more than once at a time let ref mut a @ ref mut b = U; - //~^ ERROR cannot borrow `a` as mutable more than once at a time + //~^ ERROR cannot borrow value as mutable more than once at a time //~| ERROR cannot borrow `_` as mutable more than once at a time *a = U; let ref mut a @ ref mut b = U; - //~^ ERROR cannot borrow `a` as mutable more than once at a time + //~^ ERROR cannot borrow value as mutable more than once at a time *b = U; let ref mut a @ ( - //~^ ERROR cannot borrow `a` as mutable more than once at a time + //~^ ERROR cannot borrow value as mutable more than once at a time ref mut b, [ ref mut c, @@ -50,7 +54,7 @@ fn main() { ) = (U, [U, U, U]); let ref mut a @ ( - //~^ ERROR cannot borrow `a` as mutable more than once at a time + //~^ ERROR cannot borrow value as mutable more than once at a time ref mut b, [ ref mut c, @@ -60,37 +64,37 @@ fn main() { ) = (u(), [u(), u(), u()]); let a @ (ref mut b, ref mut c) = (U, U); - //~^ ERROR cannot bind by-move with sub-bindings + //~^ ERROR borrow of moved value //~| ERROR borrow of moved value let mut val = (U, [U, U]); let a @ (b, [c, d]) = &mut val; // Same as ^-- - //~^ ERROR cannot bind by-move with sub-bindings + //~^ ERROR borrow of moved value //~| ERROR borrow of moved value let a @ &mut ref mut b = &mut U; - //~^ ERROR cannot bind by-move with sub-bindings + //~^ ERROR borrow of moved value //~| ERROR borrow of moved value let a @ &mut (ref mut b, ref mut c) = &mut (U, U); - //~^ ERROR cannot bind by-move with sub-bindings + //~^ ERROR borrow of moved value //~| ERROR borrow of moved value match Ok(U) { ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { - //~^ ERROR cannot borrow `a` as mutable more than once at a time - //~| ERROR cannot borrow `a` as mutable more than once at a time + //~^ ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time } } match Ok(U) { ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { - //~^ ERROR cannot borrow `a` as mutable more than once at a time - //~| ERROR cannot borrow `a` as mutable more than once at a time + //~^ ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time *b = U; } } match Ok(U) { ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { - //~^ ERROR cannot borrow `a` as mutable more than once at a time - //~| ERROR cannot borrow `a` as mutable more than once at a time + //~^ ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time //~| ERROR cannot borrow `_` as mutable more than once at a time //~| ERROR cannot borrow `_` as mutable more than once at a time *a = Err(U); @@ -101,8 +105,8 @@ fn main() { } match Ok(U) { ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { - //~^ ERROR cannot borrow `a` as mutable more than once at a time - //~| ERROR cannot borrow `a` as mutable more than once at a time + //~^ ERROR cannot borrow value as mutable more than once at a time + //~| ERROR cannot borrow value as mutable more than once at a time //~| ERROR cannot borrow `_` as mutable more than once at a time //~| ERROR cannot borrow `_` as mutable more than once at a time drop(a); diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr index d07ad140cc23a..4e96c6e1669c7 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr @@ -1,226 +1,265 @@ -error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:24:9 +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:28:9 | LL | let ref mut a @ ref mut b = U; | ---------^^^--------- | | | - | | another mutable borrow occurs here - | first mutable borrow occurs here + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here -error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:28:9 +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:32:9 | LL | let ref mut a @ ref mut b = U; | ---------^^^--------- | | | - | | another mutable borrow occurs here - | first mutable borrow occurs here + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here -error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:31:9 +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:35:9 | LL | let ref mut a @ ref mut b = U; | ---------^^^--------- | | | - | | another mutable borrow occurs here - | first mutable borrow occurs here + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here -error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:34:9 +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:38:9 | LL | let ref mut a @ ref mut b = U; | ---------^^^--------- | | | - | | another mutable borrow occurs here - | first mutable borrow occurs here + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here -error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:38:9 +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:42:9 | LL | let ref mut a @ ref mut b = U; | ---------^^^--------- | | | - | | another mutable borrow occurs here - | first mutable borrow occurs here + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here -error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:42:9 +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:46:9 | LL | let ref mut a @ ( | ^-------- | | - | _________first mutable borrow occurs here + | _________first mutable borrow, by `a`, occurs here | | LL | | LL | | ref mut b, - | | --------- another mutable borrow occurs here + | | --------- another mutable borrow, by `b`, occurs here LL | | [ LL | | ref mut c, - | | --------- another mutable borrow occurs here + | | --------- another mutable borrow, by `c`, occurs here LL | | ref mut d, - | | --------- another mutable borrow occurs here + | | --------- another mutable borrow, by `d`, occurs here LL | | ref e, - | | ----- also borrowed as immutable here + | | ----- also borrowed as immutable, by `e`, here LL | | ] LL | | ) = (U, [U, U, U]); | |_____^ -error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:52:9 +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:56:9 | LL | let ref mut a @ ( | ^-------- | | - | _________first mutable borrow occurs here + | _________first mutable borrow, by `a`, occurs here | | LL | | LL | | ref mut b, - | | --------- another mutable borrow occurs here + | | --------- another mutable borrow, by `b`, occurs here LL | | [ LL | | ref mut c, - | | --------- another mutable borrow occurs here + | | --------- another mutable borrow, by `c`, occurs here LL | | ref mut d, - | | --------- another mutable borrow occurs here + | | --------- another mutable borrow, by `d`, occurs here LL | | ref e, - | | ----- also borrowed as immutable here + | | ----- also borrowed as immutable, by `e`, here LL | | ] LL | | ) = (u(), [u(), u(), u()]); | |_________^ -error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/borrowck-pat-ref-mut-twice.rs:62:9 +error: borrow of moved value + --> $DIR/borrowck-pat-ref-mut-twice.rs:66:9 | LL | let a @ (ref mut b, ref mut c) = (U, U); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it - -error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/borrowck-pat-ref-mut-twice.rs:66:9 + | -^^^^---------^^---------^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `(main::U, main::U)` which does implement the `Copy` trait + +error: borrow of moved value + --> $DIR/borrowck-pat-ref-mut-twice.rs:70:9 | LL | let a @ (b, [c, d]) = &mut val; // Same as ^-- - | ^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it + | -^^^^-^^^-^^-^^ + | | | | | + | | | | value borrowed here after move + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `&mut (main::U, [main::U; 2])` which does implement the `Copy` trait -error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/borrowck-pat-ref-mut-twice.rs:70:9 +error: borrow of moved value + --> $DIR/borrowck-pat-ref-mut-twice.rs:74:9 | LL | let a @ &mut ref mut b = &mut U; - | ^^^^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it + | -^^^^^^^^--------- + | | | + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `&mut main::U` which does implement the `Copy` trait -error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/borrowck-pat-ref-mut-twice.rs:73:9 +error: borrow of moved value + --> $DIR/borrowck-pat-ref-mut-twice.rs:77:9 | LL | let a @ &mut (ref mut b, ref mut c) = &mut (U, U); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it + | -^^^^^^^^^---------^^---------^ + | | | | + | | | value borrowed here after move + | | value borrowed here after move + | value moved into `a` here + | move occurs because `a` has type `&mut (main::U, main::U)` which does implement the `Copy` trait -error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:78:9 +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:82:9 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | ---------^^^^^^---------^ | | | - | | another mutable borrow occurs here - | first mutable borrow occurs here + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here -error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:78:37 +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:82:37 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | ---------^^^^^^^---------^ | | | - | | another mutable borrow occurs here - | first mutable borrow occurs here + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here -error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:84:9 +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:88:9 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | ---------^^^^^^---------^ | | | - | | another mutable borrow occurs here - | first mutable borrow occurs here + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here -error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:84:37 +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:88:37 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | ---------^^^^^^^---------^ | | | - | | another mutable borrow occurs here - | first mutable borrow occurs here + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here -error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:91:9 +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:95:9 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | ---------^^^^^^---------^ | | | - | | another mutable borrow occurs here - | first mutable borrow occurs here + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here -error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:91:37 +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:95:37 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | ---------^^^^^^^---------^ | | | - | | another mutable borrow occurs here - | first mutable borrow occurs here + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here -error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:103:9 +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:107:9 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | ---------^^^^^^---------^ | | | - | | another mutable borrow occurs here - | first mutable borrow occurs here + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here -error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:103:37 +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:107:37 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | ---------^^^^^^^---------^ | | | - | | another mutable borrow occurs here - | first mutable borrow occurs here + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here -error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:10:11 +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:11:11 | LL | fn f1(ref mut a @ ref mut b: U) {} | ---------^^^--------- | | | - | | another mutable borrow occurs here - | first mutable borrow occurs here + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here -error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:12:11 +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:13:11 | LL | fn f2(ref mut a @ ref mut b: U) {} | ---------^^^--------- | | | - | | another mutable borrow occurs here - | first mutable borrow occurs here + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here -error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:15:9 +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:16:9 | LL | ref mut a @ [ | ^-------- | | - | _________first mutable borrow occurs here + | _________first mutable borrow, by `a`, occurs here | | LL | | LL | | [ref b @ .., _], - | | ---------- also borrowed as immutable here + | | ---------- also borrowed as immutable, by `b`, here LL | | [_, ref mut mid @ ..], - | | ---------------- another mutable borrow occurs here + | | ---------------- another mutable borrow, by `mid`, occurs here LL | | .., LL | | [..], LL | | ] : [[U; 4]; 5] | |_________^ +error: cannot borrow value as mutable more than once at a time + --> $DIR/borrowck-pat-ref-mut-twice.rs:24:22 + | +LL | fn f4_also_moved(ref mut a @ ref mut b @ c: U) {} + | ---------^^^------------- + | | | | + | | | also moved into `c` here + | | another mutable borrow, by `b`, occurs here + | first mutable borrow, by `a`, occurs here + +error: cannot move out of value because it is borrowed + --> $DIR/borrowck-pat-ref-mut-twice.rs:24:34 + | +LL | fn f4_also_moved(ref mut a @ ref mut b @ c: U) {} + | ---------^^^- + | | | + | | value moved into `c` here + | value borrowed, by `b`, here + error[E0499]: cannot borrow `_` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:24:21 + --> $DIR/borrowck-pat-ref-mut-twice.rs:28:21 | LL | let ref mut a @ ref mut b = U; | ------------^^^^^^^^^ @@ -232,7 +271,7 @@ LL | drop(a); | - first borrow later used here error[E0499]: cannot borrow `_` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:34:21 + --> $DIR/borrowck-pat-ref-mut-twice.rs:38:21 | LL | let ref mut a @ ref mut b = U; | ------------^^^^^^^^^ @@ -244,7 +283,7 @@ LL | *a = U; | ------ first borrow later used here error[E0382]: borrow of moved value - --> $DIR/borrowck-pat-ref-mut-twice.rs:62:25 + --> $DIR/borrowck-pat-ref-mut-twice.rs:66:25 | LL | let a @ (ref mut b, ref mut c) = (U, U); | ----------------^^^^^^^^^- ------ move occurs because value has type `(main::U, main::U)`, which does not implement the `Copy` trait @@ -253,7 +292,7 @@ LL | let a @ (ref mut b, ref mut c) = (U, U); | value moved here error[E0382]: borrow of moved value - --> $DIR/borrowck-pat-ref-mut-twice.rs:66:21 + --> $DIR/borrowck-pat-ref-mut-twice.rs:70:21 | LL | let a @ (b, [c, d]) = &mut val; // Same as ^-- | ------------^-- -------- move occurs because value has type `&mut (main::U, [main::U; 2])`, which does not implement the `Copy` trait @@ -262,7 +301,7 @@ LL | let a @ (b, [c, d]) = &mut val; // Same as ^-- | value moved here error[E0382]: borrow of moved value - --> $DIR/borrowck-pat-ref-mut-twice.rs:70:18 + --> $DIR/borrowck-pat-ref-mut-twice.rs:74:18 | LL | let a @ &mut ref mut b = &mut U; | ---------^^^^^^^^^ ------ move occurs because value has type `&mut main::U`, which does not implement the `Copy` trait @@ -271,7 +310,7 @@ LL | let a @ &mut ref mut b = &mut U; | value moved here error[E0382]: borrow of moved value - --> $DIR/borrowck-pat-ref-mut-twice.rs:73:30 + --> $DIR/borrowck-pat-ref-mut-twice.rs:77:30 | LL | let a @ &mut (ref mut b, ref mut c) = &mut (U, U); | ---------------------^^^^^^^^^- ----------- move occurs because value has type `&mut (main::U, main::U)`, which does not implement the `Copy` trait @@ -280,7 +319,7 @@ LL | let a @ &mut (ref mut b, ref mut c) = &mut (U, U); | value moved here error[E0499]: cannot borrow `_` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:91:24 + --> $DIR/borrowck-pat-ref-mut-twice.rs:95:24 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | ---------------^^^^^^^^^- @@ -292,7 +331,7 @@ LL | *a = Err(U); | ----------- first borrow later used here error[E0499]: cannot borrow `_` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:91:53 + --> $DIR/borrowck-pat-ref-mut-twice.rs:95:53 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | ----------------^^^^^^^^^- @@ -304,7 +343,7 @@ LL | *a = Err(U); | ----------- first borrow later used here error[E0499]: cannot borrow `_` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:103:24 + --> $DIR/borrowck-pat-ref-mut-twice.rs:107:24 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | ---------------^^^^^^^^^- @@ -316,7 +355,7 @@ LL | drop(a); | - first borrow later used here error[E0499]: cannot borrow `_` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:103:53 + --> $DIR/borrowck-pat-ref-mut-twice.rs:107:53 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | ----------------^^^^^^^^^- @@ -327,7 +366,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { LL | drop(a); | - first borrow later used here -error: aborting due to 32 previous errors +error: aborting due to 34 previous errors -Some errors have detailed explanations: E0007, E0382, E0499. -For more information about an error, try `rustc --explain E0007`. +Some errors have detailed explanations: E0382, E0499. +For more information about an error, try `rustc --explain E0382`. diff --git a/src/test/ui/pattern/bindings-after-at/copy-and-move-mixed.rs b/src/test/ui/pattern/bindings-after-at/copy-and-move-mixed.rs index db5aabc7a1453..821d4b42962bf 100644 --- a/src/test/ui/pattern/bindings-after-at/copy-and-move-mixed.rs +++ b/src/test/ui/pattern/bindings-after-at/copy-and-move-mixed.rs @@ -1,6 +1,7 @@ // Test that mixing `Copy` and non-`Copy` types in `@` patterns is forbidden. #![feature(bindings_after_at)] +#![feature(move_ref_pattern)] #[derive(Copy, Clone)] struct C; @@ -9,12 +10,9 @@ struct NC(A, B); fn main() { let a @ NC(b, c) = NC(C, C); - //~^ ERROR cannot bind by-move with sub-bindings - //~| ERROR use of moved value + //~^ ERROR use of moved value let a @ NC(b, c @ NC(d, e)) = NC(C, NC(C, C)); - //~^ ERROR cannot bind by-move with sub-bindings - //~| ERROR use of moved value - //~| ERROR cannot bind by-move with sub-bindings + //~^ ERROR use of moved value //~| ERROR use of moved value } diff --git a/src/test/ui/pattern/bindings-after-at/copy-and-move-mixed.stderr b/src/test/ui/pattern/bindings-after-at/copy-and-move-mixed.stderr index cfc35d6c32a72..7e89008a60496 100644 --- a/src/test/ui/pattern/bindings-after-at/copy-and-move-mixed.stderr +++ b/src/test/ui/pattern/bindings-after-at/copy-and-move-mixed.stderr @@ -1,23 +1,5 @@ -error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/copy-and-move-mixed.rs:11:9 - | -LL | let a @ NC(b, c) = NC(C, C); - | ^^^^^^^^^^^^ binds an already bound by-move value by moving it - -error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/copy-and-move-mixed.rs:15:9 - | -LL | let a @ NC(b, c @ NC(d, e)) = NC(C, NC(C, C)); - | ^^^^^^^^^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it - -error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/copy-and-move-mixed.rs:15:19 - | -LL | let a @ NC(b, c @ NC(d, e)) = NC(C, NC(C, C)); - | ^^^^^^^^^^^^ binds an already bound by-move value by moving it - error[E0382]: use of moved value - --> $DIR/copy-and-move-mixed.rs:11:19 + --> $DIR/copy-and-move-mixed.rs:12:19 | LL | let a @ NC(b, c) = NC(C, C); | ----------^- -------- move occurs because value has type `NC`, which does not implement the `Copy` trait @@ -45,7 +27,6 @@ LL | let a @ NC(b, c @ NC(d, e)) = NC(C, NC(C, C)); | = note: move occurs because value has type `NC`, which does not implement the `Copy` trait -error: aborting due to 6 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0007, E0382. -For more information about an error, try `rustc --explain E0007`. +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.rs b/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.rs index 1127d114145cd..b40c3e3358aa3 100644 --- a/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.rs +++ b/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.rs @@ -8,6 +8,7 @@ // this would create problems for the generalization aforementioned. #![feature(bindings_after_at)] +#![feature(move_ref_pattern)] fn main() { struct NotCopy; @@ -24,14 +25,26 @@ fn main() { let ref a @ b = &NotCopy; // OK let _: &&NotCopy = a; - let ref a @ b = NotCopy; //~ ERROR cannot bind by-move and by-ref in the same pattern - let ref mut a @ b = NotCopy; //~ ERROR cannot bind by-move and by-ref in the same pattern + let ref a @ b = NotCopy; //~ ERROR cannot move out of value because it is borrowed + let _a: &NotCopy = a; + let _b: NotCopy = b; + let ref mut a @ b = NotCopy; //~ ERROR cannot move out of value because it is borrowed + //~^ ERROR cannot move out of `_` because it is borrowed + let _a: &NotCopy = a; + let _b: NotCopy = b; match Ok(NotCopy) { - Ok(ref a @ b) | Err(ref a @ b) => {} - //~^ ERROR cannot bind by-move and by-ref in the same pattern + Ok(ref a @ b) | Err(b @ ref a) => { + //~^ ERROR cannot move out of value because it is borrowed + //~| ERROR borrow of moved value + let _a: &NotCopy = a; + let _b: NotCopy = b; + } } match NotCopy { - ref a @ b => {} - //~^ ERROR cannot bind by-move and by-ref in the same pattern + ref a @ b => { + //~^ ERROR cannot move out of value because it is borrowed + let _a: &NotCopy = a; + let _b: NotCopy = b; + } } } diff --git a/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr b/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr index b6709a8a40e23..697a8b96e6318 100644 --- a/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr +++ b/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr @@ -1,41 +1,61 @@ -error[E0009]: cannot bind by-move and by-ref in the same pattern - --> $DIR/default-binding-modes-both-sides-independent.rs:27:17 +error: cannot move out of value because it is borrowed + --> $DIR/default-binding-modes-both-sides-independent.rs:28:9 | LL | let ref a @ b = NotCopy; - | --------^ + | -----^^^- | | | - | | by-move pattern here - | by-ref pattern here + | | value moved into `b` here + | value borrowed, by `a`, here -error[E0009]: cannot bind by-move and by-ref in the same pattern - --> $DIR/default-binding-modes-both-sides-independent.rs:28:21 +error: cannot move out of value because it is borrowed + --> $DIR/default-binding-modes-both-sides-independent.rs:31:9 | LL | let ref mut a @ b = NotCopy; - | ------------^ + | ---------^^^- | | | - | | by-move pattern here - | by-ref pattern here + | | value moved into `b` here + | value borrowed, by `a`, here + +error: cannot move out of value because it is borrowed + --> $DIR/default-binding-modes-both-sides-independent.rs:36:12 + | +LL | Ok(ref a @ b) | Err(b @ ref a) => { + | -----^^^- + | | | + | | value moved into `b` here + | value borrowed, by `a`, here -error[E0009]: cannot bind by-move and by-ref in the same pattern - --> $DIR/default-binding-modes-both-sides-independent.rs:30:20 +error: borrow of moved value + --> $DIR/default-binding-modes-both-sides-independent.rs:36:29 | -LL | Ok(ref a @ b) | Err(ref a @ b) => {} - | --------^ --------^ - | | | | | - | | | | by-move pattern here - | | | by-ref pattern here - | | by-move pattern here - | by-ref pattern here +LL | Ok(ref a @ b) | Err(b @ ref a) => { + | -^^^----- + | | | + | | value borrowed here after move + | value moved into `b` here + | move occurs because `b` has type `main::NotCopy` which does implement the `Copy` trait -error[E0009]: cannot bind by-move and by-ref in the same pattern - --> $DIR/default-binding-modes-both-sides-independent.rs:34:17 +error: cannot move out of value because it is borrowed + --> $DIR/default-binding-modes-both-sides-independent.rs:44:9 | -LL | ref a @ b => {} - | --------^ +LL | ref a @ b => { + | -----^^^- | | | - | | by-move pattern here - | by-ref pattern here + | | value moved into `b` here + | value borrowed, by `a`, here + +error[E0505]: cannot move out of `_` because it is borrowed + --> $DIR/default-binding-modes-both-sides-independent.rs:31:21 + | +LL | let ref mut a @ b = NotCopy; + | ------------^ + | | | + | | move out of value occurs here + | borrow of value occurs here +LL | +LL | let _a: &NotCopy = a; + | - borrow later used here -error: aborting due to 4 previous errors +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0009`. +For more information about this error, try `rustc --explain E0505`. diff --git a/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern-pass.rs b/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern-pass.rs new file mode 100644 index 0000000000000..d2d4e61e049b2 --- /dev/null +++ b/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern-pass.rs @@ -0,0 +1,31 @@ +// check-pass + +#![feature(move_ref_pattern)] + +fn main() {} + +struct U; + +fn slice() { + let mut arr = [U, U, U, U, U, U, U, U]; + let [ref _x0, _x1, _, mut _x3, .., ref _x6, _x7] = arr; + _x3 = U; + let [ref mut _x0, _, ref _x2, _, _x4, ref mut _x5, _x6, _] = arr; + *_x5 = U; + let [_, _, _x2, _, _, _x5, _, _] = arr; + *_x0 = U; + let [ref _x0, ..] = arr; + let [_x0, ..] = arr; +} + +fn tuple() { + let mut tup = (U, U, U, U, U); + let (ref _x0, mut _x1, ref _x2, ..) = tup; + _x1 = U; + let (ref mut _x0, _, _, ref _x3, _x4) = tup; + let (_, _, _, _x3, _) = tup; + *_x0 = U; + drop(_x2); + drop(tup.2); + let (_x0, _, _, ..) = tup; +} diff --git a/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.rs b/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.rs new file mode 100644 index 0000000000000..3ee008fd84f09 --- /dev/null +++ b/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.rs @@ -0,0 +1,50 @@ +#![feature(move_ref_pattern)] + +fn main() {} + +struct U; + +fn slice() { + let mut arr = [U, U, U, U, U]; + let hold_all = &arr; + let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr; //~ ERROR cannot move out of `arr[..]` + _x1 = U; //~ ERROR cannot assign twice to immutable variable `_x1` + drop(hold_all); + let [_x0, ..] = arr; //~ ERROR cannot move out of `arr[..]` + drop(_x0_hold); + let [_, _, ref mut _x2, _x3, mut _x4] = arr; + //~^ ERROR cannot borrow `arr[..]` as mutable + //~| ERROR cannot move out of `arr[..]` because it is borrowed + //~| ERROR cannot move out of `arr[..]` because it is borrowed + drop(xs_hold); +} + +fn tuple() { + let mut tup = (U, U, U, U); + let (ref _x0, _x1, ref _x2, ..) = tup; + _x1 = U; //~ ERROR cannot assign twice to immutable variable + let _x0_hold = &mut tup.0; //~ ERROR cannot borrow `tup.0` as mutable because it is also + let (ref mut _x0_hold, ..) = tup; //~ ERROR cannot borrow `tup.0` as mutable because it is also + *_x0 = U; //~ ERROR cannot assign to `*_x0` which is behind a `&` reference + *_x2 = U; //~ ERROR cannot assign to `*_x2` which is behind a `&` reference + drop(tup.1); //~ ERROR use of moved value: `tup.1` + let _x1_hold = &tup.1; //~ ERROR borrow of moved value: `tup.1` + let (.., ref mut _x3) = tup; + let _x3_hold = &tup.3; //~ ERROR cannot borrow `tup.3` as immutable + let _x3_hold = &mut tup.3; //~ ERROR cannot borrow `tup.3` as mutable more + let (.., ref mut _x4_hold) = tup; //~ ERROR cannot borrow `tup.3` as mutable more + let (.., ref _x4_hold) = tup; //~ ERROR cannot borrow `tup.3` as immutable + drop(_x3); +} + +fn closure() { + let mut tup = (U, U, U); + let c1 = || { + let (ref _x0, _x1, _) = tup; + }; + let c2 = || { + //~^ ERROR use of moved value + let (ref mut _x0, _, _x2) = tup; + }; + drop(c1); +} diff --git a/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr b/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr new file mode 100644 index 0000000000000..d718ee29cf9b5 --- /dev/null +++ b/src/test/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr @@ -0,0 +1,208 @@ +error[E0505]: cannot move out of `arr[..]` because it is borrowed + --> $DIR/borrowck-move-ref-pattern.rs:10:24 + | +LL | let hold_all = &arr; + | ---- borrow of `arr` occurs here +LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr; + | ^^^ move out of `arr[..]` occurs here +LL | _x1 = U; +LL | drop(hold_all); + | -------- borrow later used here + +error[E0384]: cannot assign twice to immutable variable `_x1` + --> $DIR/borrowck-move-ref-pattern.rs:11:5 + | +LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr; + | --- + | | + | first assignment to `_x1` + | help: make this binding mutable: `mut _x1` +LL | _x1 = U; + | ^^^^^^^ cannot assign twice to immutable variable + +error[E0505]: cannot move out of `arr[..]` because it is borrowed + --> $DIR/borrowck-move-ref-pattern.rs:13:10 + | +LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr; + | ------------ borrow of `arr[..]` occurs here +... +LL | let [_x0, ..] = arr; + | ^^^ move out of `arr[..]` occurs here +LL | drop(_x0_hold); + | -------- borrow later used here + +error[E0502]: cannot borrow `arr[..]` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-move-ref-pattern.rs:15:16 + | +LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr; + | ---------------- immutable borrow occurs here +... +LL | let [_, _, ref mut _x2, _x3, mut _x4] = arr; + | ^^^^^^^^^^^ mutable borrow occurs here +... +LL | drop(xs_hold); + | ------- immutable borrow later used here + +error[E0505]: cannot move out of `arr[..]` because it is borrowed + --> $DIR/borrowck-move-ref-pattern.rs:15:29 + | +LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr; + | ---------------- borrow of `arr[..]` occurs here +... +LL | let [_, _, ref mut _x2, _x3, mut _x4] = arr; + | ^^^ move out of `arr[..]` occurs here +... +LL | drop(xs_hold); + | ------- borrow later used here + +error[E0505]: cannot move out of `arr[..]` because it is borrowed + --> $DIR/borrowck-move-ref-pattern.rs:15:34 + | +LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr; + | ---------------- borrow of `arr[..]` occurs here +... +LL | let [_, _, ref mut _x2, _x3, mut _x4] = arr; + | ^^^^^^^ move out of `arr[..]` occurs here +... +LL | drop(xs_hold); + | ------- borrow later used here + +error[E0384]: cannot assign twice to immutable variable `_x1` + --> $DIR/borrowck-move-ref-pattern.rs:25:5 + | +LL | let (ref _x0, _x1, ref _x2, ..) = tup; + | --- + | | + | first assignment to `_x1` + | help: make this binding mutable: `mut _x1` +LL | _x1 = U; + | ^^^^^^^ cannot assign twice to immutable variable + +error[E0502]: cannot borrow `tup.0` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-move-ref-pattern.rs:26:20 + | +LL | let (ref _x0, _x1, ref _x2, ..) = tup; + | ------- immutable borrow occurs here +LL | _x1 = U; +LL | let _x0_hold = &mut tup.0; + | ^^^^^^^^^^ mutable borrow occurs here +LL | let (ref mut _x0_hold, ..) = tup; +LL | *_x0 = U; + | -------- immutable borrow later used here + +error[E0502]: cannot borrow `tup.0` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-move-ref-pattern.rs:27:10 + | +LL | let (ref _x0, _x1, ref _x2, ..) = tup; + | ------- immutable borrow occurs here +... +LL | let (ref mut _x0_hold, ..) = tup; + | ^^^^^^^^^^^^^^^^ mutable borrow occurs here +LL | *_x0 = U; + | -------- immutable borrow later used here + +error[E0594]: cannot assign to `*_x0` which is behind a `&` reference + --> $DIR/borrowck-move-ref-pattern.rs:28:5 + | +LL | let (ref _x0, _x1, ref _x2, ..) = tup; + | ------- help: consider changing this to be a mutable reference: `ref mut _x0` +... +LL | *_x0 = U; + | ^^^^^^^^ `_x0` is a `&` reference, so the data it refers to cannot be written + +error[E0594]: cannot assign to `*_x2` which is behind a `&` reference + --> $DIR/borrowck-move-ref-pattern.rs:29:5 + | +LL | let (ref _x0, _x1, ref _x2, ..) = tup; + | ------- help: consider changing this to be a mutable reference: `ref mut _x2` +... +LL | *_x2 = U; + | ^^^^^^^^ `_x2` is a `&` reference, so the data it refers to cannot be written + +error[E0382]: use of moved value: `tup.1` + --> $DIR/borrowck-move-ref-pattern.rs:30:10 + | +LL | let (ref _x0, _x1, ref _x2, ..) = tup; + | --- value moved here +... +LL | drop(tup.1); + | ^^^^^ value used here after move + | + = note: move occurs because `tup.1` has type `U`, which does not implement the `Copy` trait + +error[E0382]: borrow of moved value: `tup.1` + --> $DIR/borrowck-move-ref-pattern.rs:31:20 + | +LL | drop(tup.1); + | ----- value moved here +LL | let _x1_hold = &tup.1; + | ^^^^^^ value borrowed here after move + | + = note: move occurs because `tup.1` has type `U`, which does not implement the `Copy` trait + +error[E0502]: cannot borrow `tup.3` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-move-ref-pattern.rs:33:20 + | +LL | let (.., ref mut _x3) = tup; + | ----------- mutable borrow occurs here +LL | let _x3_hold = &tup.3; + | ^^^^^^ immutable borrow occurs here +... +LL | drop(_x3); + | --- mutable borrow later used here + +error[E0499]: cannot borrow `tup.3` as mutable more than once at a time + --> $DIR/borrowck-move-ref-pattern.rs:34:20 + | +LL | let (.., ref mut _x3) = tup; + | ----------- first mutable borrow occurs here +LL | let _x3_hold = &tup.3; +LL | let _x3_hold = &mut tup.3; + | ^^^^^^^^^^ second mutable borrow occurs here +... +LL | drop(_x3); + | --- first borrow later used here + +error[E0499]: cannot borrow `tup.3` as mutable more than once at a time + --> $DIR/borrowck-move-ref-pattern.rs:35:14 + | +LL | let (.., ref mut _x3) = tup; + | ----------- first mutable borrow occurs here +... +LL | let (.., ref mut _x4_hold) = tup; + | ^^^^^^^^^^^^^^^^ second mutable borrow occurs here +LL | let (.., ref _x4_hold) = tup; +LL | drop(_x3); + | --- first borrow later used here + +error[E0502]: cannot borrow `tup.3` as immutable because it is also borrowed as mutable + --> $DIR/borrowck-move-ref-pattern.rs:36:14 + | +LL | let (.., ref mut _x3) = tup; + | ----------- mutable borrow occurs here +... +LL | let (.., ref _x4_hold) = tup; + | ^^^^^^^^^^^^ immutable borrow occurs here +LL | drop(_x3); + | --- mutable borrow later used here + +error[E0382]: use of moved value: `tup` + --> $DIR/borrowck-move-ref-pattern.rs:45:14 + | +LL | let mut tup = (U, U, U); + | ------- move occurs because `tup` has type `(U, U, U)`, which does not implement the `Copy` trait +LL | let c1 = || { + | -- value moved into closure here +LL | let (ref _x0, _x1, _) = tup; + | --- variable moved due to use in closure +LL | }; +LL | let c2 = || { + | ^^ value used here after move +LL | +LL | let (ref mut _x0, _, _x2) = tup; + | --- use occurs due to use in closure + +error: aborting due to 18 previous errors + +Some errors have detailed explanations: E0382, E0384, E0499, E0502, E0505, E0594. +For more information about an error, try `rustc --explain E0382`. diff --git a/src/test/ui/pattern/move-ref-patterns/by-move-sub-pat-unreachable.rs b/src/test/ui/pattern/move-ref-patterns/by-move-sub-pat-unreachable.rs new file mode 100644 index 0000000000000..08fb5cd2e1688 --- /dev/null +++ b/src/test/ui/pattern/move-ref-patterns/by-move-sub-pat-unreachable.rs @@ -0,0 +1,15 @@ +// When conflicts between by-move bindings in `by_move_1 @ has_by_move` patterns +// happen and that code is unreachable according to borrowck, we accept this code. +// In particular, we want to ensure here that an ICE does not happen, which it did originally. + +// check-pass + +#![feature(move_ref_pattern)] +#![feature(bindings_after_at)] + +fn main() { + return; + + struct S; + let a @ (b, c) = (S, S); +} diff --git a/src/test/ui/pattern/move-ref-patterns/feature-gate-move_ref_pattern.rs b/src/test/ui/pattern/move-ref-patterns/feature-gate-move_ref_pattern.rs new file mode 100644 index 0000000000000..fb92eb1ba32e0 --- /dev/null +++ b/src/test/ui/pattern/move-ref-patterns/feature-gate-move_ref_pattern.rs @@ -0,0 +1,23 @@ +fn main() { + #[derive(Clone)] + struct X { + x: (), + } + let mut tup = (X { x: () }, X { x: () }); + match Some(tup.clone()) { + Some((y, ref z)) => {} + //~^ ERROR binding by-move and by-ref in the same pattern is unstable + None => panic!(), + } + + let (ref a, b) = tup.clone(); + //~^ ERROR binding by-move and by-ref in the same pattern is unstable + + let (a, mut b) = &tup; + //~^ ERROR binding by-move and by-ref in the same pattern is unstable + //~| ERROR cannot move out of a shared reference + + let (mut a, b) = &mut tup; + //~^ ERROR binding by-move and by-ref in the same pattern is unstable + //~| ERROR cannot move out of a mutable reference +} diff --git a/src/test/ui/pattern/move-ref-patterns/feature-gate-move_ref_pattern.stderr b/src/test/ui/pattern/move-ref-patterns/feature-gate-move_ref_pattern.stderr new file mode 100644 index 0000000000000..8aef220c37519 --- /dev/null +++ b/src/test/ui/pattern/move-ref-patterns/feature-gate-move_ref_pattern.stderr @@ -0,0 +1,66 @@ +error[E0658]: binding by-move and by-ref in the same pattern is unstable + --> $DIR/feature-gate-move_ref_pattern.rs:8:15 + | +LL | Some((y, ref z)) => {} + | ^ ----- by-ref pattern here + | | + | by-move pattern here + | + = note: for more information, see https://github.com/rust-lang/rust/issues/68354 + = help: add `#![feature(move_ref_pattern)]` to the crate attributes to enable + +error[E0658]: binding by-move and by-ref in the same pattern is unstable + --> $DIR/feature-gate-move_ref_pattern.rs:13:17 + | +LL | let (ref a, b) = tup.clone(); + | ----- ^ by-move pattern here + | | + | by-ref pattern here + | + = note: for more information, see https://github.com/rust-lang/rust/issues/68354 + = help: add `#![feature(move_ref_pattern)]` to the crate attributes to enable + +error[E0658]: binding by-move and by-ref in the same pattern is unstable + --> $DIR/feature-gate-move_ref_pattern.rs:16:13 + | +LL | let (a, mut b) = &tup; + | - ^^^^^ by-move pattern here + | | + | by-ref pattern here + | + = note: for more information, see https://github.com/rust-lang/rust/issues/68354 + = help: add `#![feature(move_ref_pattern)]` to the crate attributes to enable + +error[E0658]: binding by-move and by-ref in the same pattern is unstable + --> $DIR/feature-gate-move_ref_pattern.rs:20:10 + | +LL | let (mut a, b) = &mut tup; + | ^^^^^ - by-ref pattern here + | | + | by-move pattern here + | + = note: for more information, see https://github.com/rust-lang/rust/issues/68354 + = help: add `#![feature(move_ref_pattern)]` to the crate attributes to enable + +error[E0507]: cannot move out of a shared reference + --> $DIR/feature-gate-move_ref_pattern.rs:16:22 + | +LL | let (a, mut b) = &tup; + | ----- ^^^^ + | | + | data moved here + | move occurs because `b` has type `main::X`, which does not implement the `Copy` trait + +error[E0507]: cannot move out of a mutable reference + --> $DIR/feature-gate-move_ref_pattern.rs:20:22 + | +LL | let (mut a, b) = &mut tup; + | ----- ^^^^^^^^ + | | + | data moved here + | move occurs because `a` has type `main::X`, which does not implement the `Copy` trait + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0507, E0658. +For more information about an error, try `rustc --explain E0507`. diff --git a/src/test/ui/issues/issue-53840.rs b/src/test/ui/pattern/move-ref-patterns/issue-53840.rs similarity index 64% rename from src/test/ui/issues/issue-53840.rs rename to src/test/ui/pattern/move-ref-patterns/issue-53840.rs index e854d24ab9756..ab7d10d9f837d 100644 --- a/src/test/ui/issues/issue-53840.rs +++ b/src/test/ui/pattern/move-ref-patterns/issue-53840.rs @@ -1,3 +1,7 @@ +// check-pass + +#![feature(move_ref_pattern)] + enum E { Foo(String, String, String), } @@ -11,10 +15,8 @@ fn main() { let bar = Bar { a: "1".to_string(), b: "2".to_string() }; match E::Foo("".into(), "".into(), "".into()) { E::Foo(a, b, ref c) => {} -//~^ ERROR cannot bind by-move and by-ref in the same pattern } match bar { - Bar {a, ref b} => {} -//~^ ERROR cannot bind by-move and by-ref in the same pattern + Bar { a, ref b } => {} } } diff --git a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-inside.rs b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-inside.rs new file mode 100644 index 0000000000000..4c3ca62e16586 --- /dev/null +++ b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-inside.rs @@ -0,0 +1,122 @@ +#![feature(move_ref_pattern)] + +fn main() { + struct S; // Not `Copy`. + + let mut tup0 = (S, S); + let mut tup1 = (S, S, S); + let tup2 = (S, S); + let tup3 = (S, S, S); + let tup4 = (S, S); + let mut arr0 = [S, S, S]; + let mut arr1 = [S, S, S, S, S]; + let arr2 = [S, S, S]; + let arr3 = [S, S, S, S, S]; + + // The `mov` bindings require that we capture the scrutinees by-move. + let mut closure = || { + // Tuples... + let (ref mut borrow, mov) = tup0; + let (mov, _, ref mut borrow) = tup1; + let (ref borrow, mov) = tup2; + let (mov, _, ref borrow) = tup3; + let (ref borrow, mov) = tup4; + // Arrays... + let [mov @ .., ref borrow] = arr0; + let [_, ref mut borrow @ .., _, mov] = arr1; + let [mov @ .., ref borrow] = arr2; + let [_, ref borrow @ .., _, mov] = arr3; + }; + + // Now we try to borrow and move the captures, which should result in errors... + // ...for tuples: + drop(&tup0); //~ ERROR borrow of moved value: `tup0` + drop(&tup1); //~ ERROR borrow of moved value: `tup1` + drop(&tup2); //~ ERROR borrow of moved value: `tup2` + drop(&tup3); //~ ERROR borrow of moved value: `tup3` + // Ostensibly this should compile. + // However, because closures don't capture individual fields, which is changed in RFC 2229, + // this won't compile because the entire product is moved into the closure. + // The same applies to the array patterns below. + drop(&tup4.0); //~ ERROR borrow of moved value: `tup4` + // ...for arrays: + drop(&arr0); //~ ERROR borrow of moved value: `arr0` + let [_, mov1, mov2, mov3, _] = &arr1; //~ ERROR borrow of moved value: `arr1` + drop(&arr2); //~ ERROR borrow of moved value: `arr2` + let [_, mov1, mov2, mov3, _] = &arr3; //~ ERROR borrow of moved value: `arr3` + + // Let's redo ^--- with a `match` + sum type: + macro_rules! m { + ($p:pat = $s:expr) => { + match $s { + Some($p) => {} + _ => {} + } + }; + } + let mut tup0: Option<(S, S)> = None; + let mut tup1: Option<(S, S, S)> = None; + let tup2: Option<(S, S)> = None; + let tup3: Option<(S, S, S)> = None; + let tup4: Option<(S, S)> = None; + let mut arr0: Option<[S; 3]> = None; + let mut arr1: Option<[S; 5]> = None; + let arr2: Option<[S; 3]> = None; + let arr3: Option<[S; 5]> = None; + let mut closure = || { + m!((ref mut borrow, mov) = tup0); + m!((mov, _, ref mut borrow) = tup1); + m!((ref borrow, mov) = tup2); + m!((mov, _, ref borrow) = tup3); + m!((ref borrow, mov) = tup4); + m!([mov @ .., ref borrow] = arr0); + m!([_, ref mut borrow @ .., _, mov] = arr1); + m!([mov @ .., ref borrow] = arr2); + m!([_, ref borrow @ .., _, mov] = arr3); + }; + drop(&tup0); //~ ERROR borrow of moved value: `tup0` + drop(&tup1); //~ ERROR borrow of moved value: `tup1` + drop(&tup2); //~ ERROR borrow of moved value: `tup2` + drop(&tup3); //~ ERROR borrow of moved value: `tup3` + m!((ref x, _) = &tup4); //~ ERROR borrow of moved value: `tup4` + drop(&arr0); //~ ERROR borrow of moved value: `arr0` + m!([_, mov1, mov2, mov3, _] = &arr1); //~ ERROR borrow of moved value: `arr1` + drop(&arr2); //~ ERROR borrow of moved value: `arr2` + m!([_, mov1, mov2, mov3, _] = &arr3); //~ ERROR borrow of moved value: `arr3` + + // Let's redo ^--- with `if let` (which may diverge from `match` in the future): + macro_rules! m { + ($p:pat = $s:expr) => { + if let Some($p) = $s {} + }; + } + let mut tup0: Option<(S, S)> = None; + let mut tup1: Option<(S, S, S)> = None; + let tup2: Option<(S, S)> = None; + let tup3: Option<(S, S, S)> = None; + let tup4: Option<(S, S)> = None; + let mut arr0: Option<[S; 3]> = None; + let mut arr1: Option<[S; 5]> = None; + let arr2: Option<[S; 3]> = None; + let arr3: Option<[S; 5]> = None; + let mut closure = || { + m!((ref mut borrow, mov) = tup0); + m!((mov, _, ref mut borrow) = tup1); + m!((ref borrow, mov) = tup2); + m!((mov, _, ref borrow) = tup3); + m!((ref borrow, mov) = tup4); + m!([mov @ .., ref borrow] = arr0); + m!([_, ref mut borrow @ .., _, mov] = arr1); + m!([mov @ .., ref borrow] = arr2); + m!([_, ref borrow @ .., _, mov] = arr3); + }; + drop(&tup0); //~ ERROR borrow of moved value: `tup0` + drop(&tup1); //~ ERROR borrow of moved value: `tup1` + drop(&tup2); //~ ERROR borrow of moved value: `tup2` + drop(&tup3); //~ ERROR borrow of moved value: `tup3` + m!((ref x, _) = &tup4); //~ ERROR borrow of moved value: `tup4` + drop(&arr0); //~ ERROR borrow of moved value: `arr0` + m!([_, mov1, mov2, mov3, _] = &arr1); //~ ERROR borrow of moved value: `arr1` + drop(&arr2); //~ ERROR borrow of moved value: `arr2` + m!([_, mov1, mov2, mov3, _] = &arr3); //~ ERROR borrow of moved value: `arr3` +} diff --git a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-inside.stderr b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-inside.stderr new file mode 100644 index 0000000000000..9159e3e221349 --- /dev/null +++ b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-inside.stderr @@ -0,0 +1,404 @@ +error[E0382]: borrow of moved value: `tup0` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:33:10 + | +LL | let mut tup0 = (S, S); + | -------- move occurs because `tup0` has type `(main::S, main::S)`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +LL | // Tuples... +LL | let (ref mut borrow, mov) = tup0; + | ---- variable moved due to use in closure +... +LL | drop(&tup0); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `tup1` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:34:10 + | +LL | let mut tup1 = (S, S, S); + | -------- move occurs because `tup1` has type `(main::S, main::S, main::S)`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | let (mov, _, ref mut borrow) = tup1; + | ---- variable moved due to use in closure +... +LL | drop(&tup1); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `tup2` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:35:10 + | +LL | let tup2 = (S, S); + | ---- move occurs because `tup2` has type `(main::S, main::S)`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | let (ref borrow, mov) = tup2; + | ---- variable moved due to use in closure +... +LL | drop(&tup2); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `tup3` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:36:10 + | +LL | let tup3 = (S, S, S); + | ---- move occurs because `tup3` has type `(main::S, main::S, main::S)`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | let (mov, _, ref borrow) = tup3; + | ---- variable moved due to use in closure +... +LL | drop(&tup3); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `tup4` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:41:10 + | +LL | let tup4 = (S, S); + | ---- move occurs because `tup4` has type `(main::S, main::S)`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | let (ref borrow, mov) = tup4; + | ---- variable moved due to use in closure +... +LL | drop(&tup4.0); + | ^^^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `arr0` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:43:10 + | +LL | let mut arr0 = [S, S, S]; + | -------- move occurs because `arr0` has type `[main::S; 3]`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | let [mov @ .., ref borrow] = arr0; + | ---- variable moved due to use in closure +... +LL | drop(&arr0); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `arr1` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:44:36 + | +LL | let mut arr1 = [S, S, S, S, S]; + | -------- move occurs because `arr1` has type `[main::S; 5]`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | let [_, ref mut borrow @ .., _, mov] = arr1; + | ---- variable moved due to use in closure +... +LL | let [_, mov1, mov2, mov3, _] = &arr1; + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `arr2` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:45:10 + | +LL | let arr2 = [S, S, S]; + | ---- move occurs because `arr2` has type `[main::S; 3]`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | let [mov @ .., ref borrow] = arr2; + | ---- variable moved due to use in closure +... +LL | drop(&arr2); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `arr3` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:46:36 + | +LL | let arr3 = [S, S, S, S, S]; + | ---- move occurs because `arr3` has type `[main::S; 5]`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | let [_, ref borrow @ .., _, mov] = arr3; + | ---- variable moved due to use in closure +... +LL | let [_, mov1, mov2, mov3, _] = &arr3; + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `tup0` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:77:10 + | +LL | let mut tup0: Option<(S, S)> = None; + | -------- move occurs because `tup0` has type `std::option::Option<(main::S, main::S)>`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +LL | m!((ref mut borrow, mov) = tup0); + | ---- variable moved due to use in closure +... +LL | drop(&tup0); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `tup1` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:78:10 + | +LL | let mut tup1: Option<(S, S, S)> = None; + | -------- move occurs because `tup1` has type `std::option::Option<(main::S, main::S, main::S)>`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +LL | m!((ref mut borrow, mov) = tup0); +LL | m!((mov, _, ref mut borrow) = tup1); + | ---- variable moved due to use in closure +... +LL | drop(&tup1); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `tup2` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:79:10 + | +LL | let tup2: Option<(S, S)> = None; + | ---- move occurs because `tup2` has type `std::option::Option<(main::S, main::S)>`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | m!((ref borrow, mov) = tup2); + | ---- variable moved due to use in closure +... +LL | drop(&tup2); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `tup3` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:80:10 + | +LL | let tup3: Option<(S, S, S)> = None; + | ---- move occurs because `tup3` has type `std::option::Option<(main::S, main::S, main::S)>`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | m!((mov, _, ref borrow) = tup3); + | ---- variable moved due to use in closure +... +LL | drop(&tup3); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `tup4` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:81:21 + | +LL | let tup4: Option<(S, S)> = None; + | ---- move occurs because `tup4` has type `std::option::Option<(main::S, main::S)>`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | m!((ref borrow, mov) = tup4); + | ---- variable moved due to use in closure +... +LL | m!((ref x, _) = &tup4); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `arr0` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:82:10 + | +LL | let mut arr0: Option<[S; 3]> = None; + | -------- move occurs because `arr0` has type `std::option::Option<[main::S; 3]>`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | m!([mov @ .., ref borrow] = arr0); + | ---- variable moved due to use in closure +... +LL | drop(&arr0); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `arr1` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:83:35 + | +LL | let mut arr1: Option<[S; 5]> = None; + | -------- move occurs because `arr1` has type `std::option::Option<[main::S; 5]>`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | m!([_, ref mut borrow @ .., _, mov] = arr1); + | ---- variable moved due to use in closure +... +LL | m!([_, mov1, mov2, mov3, _] = &arr1); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `arr2` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:84:10 + | +LL | let arr2: Option<[S; 3]> = None; + | ---- move occurs because `arr2` has type `std::option::Option<[main::S; 3]>`, which does not implement the `Copy` trait +LL | let arr3: Option<[S; 5]> = None; +LL | let mut closure = || { + | -- value moved into closure here +... +LL | m!([mov @ .., ref borrow] = arr2); + | ---- variable moved due to use in closure +... +LL | drop(&arr2); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `arr3` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:85:35 + | +LL | let arr3: Option<[S; 5]> = None; + | ---- move occurs because `arr3` has type `std::option::Option<[main::S; 5]>`, which does not implement the `Copy` trait +LL | let mut closure = || { + | -- value moved into closure here +... +LL | m!([_, ref borrow @ .., _, mov] = arr3); + | ---- variable moved due to use in closure +... +LL | m!([_, mov1, mov2, mov3, _] = &arr3); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `tup0` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:113:10 + | +LL | let mut tup0: Option<(S, S)> = None; + | -------- move occurs because `tup0` has type `std::option::Option<(main::S, main::S)>`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +LL | m!((ref mut borrow, mov) = tup0); + | ---- variable moved due to use in closure +... +LL | drop(&tup0); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `tup1` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:114:10 + | +LL | let mut tup1: Option<(S, S, S)> = None; + | -------- move occurs because `tup1` has type `std::option::Option<(main::S, main::S, main::S)>`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +LL | m!((ref mut borrow, mov) = tup0); +LL | m!((mov, _, ref mut borrow) = tup1); + | ---- variable moved due to use in closure +... +LL | drop(&tup1); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `tup2` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:115:10 + | +LL | let tup2: Option<(S, S)> = None; + | ---- move occurs because `tup2` has type `std::option::Option<(main::S, main::S)>`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | m!((ref borrow, mov) = tup2); + | ---- variable moved due to use in closure +... +LL | drop(&tup2); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `tup3` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:116:10 + | +LL | let tup3: Option<(S, S, S)> = None; + | ---- move occurs because `tup3` has type `std::option::Option<(main::S, main::S, main::S)>`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | m!((mov, _, ref borrow) = tup3); + | ---- variable moved due to use in closure +... +LL | drop(&tup3); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `tup4` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:117:21 + | +LL | let tup4: Option<(S, S)> = None; + | ---- move occurs because `tup4` has type `std::option::Option<(main::S, main::S)>`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | m!((ref borrow, mov) = tup4); + | ---- variable moved due to use in closure +... +LL | m!((ref x, _) = &tup4); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `arr0` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:118:10 + | +LL | let mut arr0: Option<[S; 3]> = None; + | -------- move occurs because `arr0` has type `std::option::Option<[main::S; 3]>`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | m!([mov @ .., ref borrow] = arr0); + | ---- variable moved due to use in closure +... +LL | drop(&arr0); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `arr1` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:119:35 + | +LL | let mut arr1: Option<[S; 5]> = None; + | -------- move occurs because `arr1` has type `std::option::Option<[main::S; 5]>`, which does not implement the `Copy` trait +... +LL | let mut closure = || { + | -- value moved into closure here +... +LL | m!([_, ref mut borrow @ .., _, mov] = arr1); + | ---- variable moved due to use in closure +... +LL | m!([_, mov1, mov2, mov3, _] = &arr1); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `arr2` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:120:10 + | +LL | let arr2: Option<[S; 3]> = None; + | ---- move occurs because `arr2` has type `std::option::Option<[main::S; 3]>`, which does not implement the `Copy` trait +LL | let arr3: Option<[S; 5]> = None; +LL | let mut closure = || { + | -- value moved into closure here +... +LL | m!([mov @ .., ref borrow] = arr2); + | ---- variable moved due to use in closure +... +LL | drop(&arr2); + | ^^^^^ value borrowed here after move + +error[E0382]: borrow of moved value: `arr3` + --> $DIR/move-ref-patterns-closure-captures-inside.rs:121:35 + | +LL | let arr3: Option<[S; 5]> = None; + | ---- move occurs because `arr3` has type `std::option::Option<[main::S; 5]>`, which does not implement the `Copy` trait +LL | let mut closure = || { + | -- value moved into closure here +... +LL | m!([_, ref borrow @ .., _, mov] = arr3); + | ---- variable moved due to use in closure +... +LL | m!([_, mov1, mov2, mov3, _] = &arr3); + | ^^^^^ value borrowed here after move + +error: aborting due to 27 previous errors + +For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-pass.rs b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-pass.rs new file mode 100644 index 0000000000000..e1844d36e4aa4 --- /dev/null +++ b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures-pass.rs @@ -0,0 +1,30 @@ +// check-pass + +#![feature(move_ref_pattern)] + +fn main() { + struct U; + fn accept_fn_once(_: impl FnOnce()) {} + fn accept_fn_mut(_: impl FnMut()) {} + fn accept_fn(_: impl Fn()) {} + + let mut tup = (U, U, U); + let (ref _x0, _x1, ref mut _x2) = tup; + let c1 = || { + drop::<&U>(_x0); + drop::(_x1); + drop::<&mut U>(_x2); + }; + accept_fn_once(c1); + + let c2 = || { + drop::<&U>(_x0); + drop::<&mut U>(_x2); + }; + accept_fn_mut(c2); + + let c3 = || { + drop::<&U>(_x0); + }; + accept_fn(c3); +} diff --git a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.rs b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.rs new file mode 100644 index 0000000000000..7f1c02c05cb0d --- /dev/null +++ b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.rs @@ -0,0 +1,34 @@ +#![feature(move_ref_pattern)] + +fn main() { + struct U; + fn accept_fn_once(_: &impl FnOnce()) {} + fn accept_fn_mut(_: &impl FnMut()) {} + fn accept_fn(_: &impl Fn()) {} + + let mut tup = (U, U, U); + let (ref _x0, _x1, ref mut _x2) = tup; + let c1 = || { + //~^ ERROR expected a closure that implements the `FnMut` + //~| ERROR expected a closure that implements the `Fn` + drop::<&U>(_x0); + drop::(_x1); + drop::<&mut U>(_x2); + }; + accept_fn_once(&c1); + accept_fn_mut(&c1); + accept_fn(&c1); + + let c2 = || { + //~^ ERROR expected a closure that implements the `Fn` + drop::<&U>(_x0); + drop::<&mut U>(_x2); + }; + accept_fn_mut(&c2); + accept_fn(&c2); + + let c3 = || { + drop::<&U>(_x0); + }; + accept_fn(&c3); +} diff --git a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.stderr b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.stderr new file mode 100644 index 0000000000000..ca82353c1c9ab --- /dev/null +++ b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.stderr @@ -0,0 +1,39 @@ +error[E0525]: expected a closure that implements the `FnMut` trait, but this closure only implements `FnOnce` + --> $DIR/move-ref-patterns-closure-captures.rs:11:14 + | +LL | let c1 = || { + | ^^ this closure implements `FnOnce`, not `FnMut` +... +LL | drop::(_x1); + | --- closure is `FnOnce` because it moves the variable `_x1` out of its environment +... +LL | accept_fn_mut(&c1); + | ------------- the requirement to implement `FnMut` derives from here + +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce` + --> $DIR/move-ref-patterns-closure-captures.rs:11:14 + | +LL | let c1 = || { + | ^^ this closure implements `FnOnce`, not `Fn` +... +LL | drop::(_x1); + | --- closure is `FnOnce` because it moves the variable `_x1` out of its environment +... +LL | accept_fn(&c1); + | --------- the requirement to implement `Fn` derives from here + +error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut` + --> $DIR/move-ref-patterns-closure-captures.rs:22:14 + | +LL | let c2 = || { + | ^^ this closure implements `FnMut`, not `Fn` +... +LL | drop::<&mut U>(_x2); + | --- closure is `FnMut` because it mutates the variable `_x2` here +... +LL | accept_fn(&c2); + | --------- the requirement to implement `Fn` derives from here + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0525`. 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 new file mode 100644 index 0000000000000..5c51c47d9798a --- /dev/null +++ b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.rs @@ -0,0 +1,16 @@ +#![feature(move_ref_pattern)] + +fn main() { + struct U; + + // A tuple is a "non-reference pattern". + // A `mut` binding pattern resets the binding mode to by-value. + + 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 new file mode 100644 index 0000000000000..fe7f71e6c46cd --- /dev/null +++ b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-default-binding-modes.stderr @@ -0,0 +1,21 @@ +error[E0507]: cannot move out of a shared reference + --> $DIR/move-ref-patterns-default-binding-modes.rs:10:22 + | +LL | let (a, mut b) = &p; + | ----- ^^ + | | + | data moved here + | move occurs because `b` has type `main::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:14:22 + | +LL | let (a, mut b) = &mut p; + | ----- ^^^^^^ + | | + | data moved here + | move occurs because `b` has type `main::U`, which does not implement the `Copy` trait + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-dynamic-semantics.rs b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-dynamic-semantics.rs new file mode 100644 index 0000000000000..c78695390b598 --- /dev/null +++ b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-dynamic-semantics.rs @@ -0,0 +1,81 @@ +// run-pass + +// This test checks the dynamic semantics and drop order of pattern matching +// where a product pattern has both a by-move and by-ref binding. + +#![feature(move_ref_pattern)] + +use std::cell::RefCell; +use std::rc::Rc; + +struct X { + x: Box, + d: DropOrderListPtr, +} + +type DropOrderListPtr = Rc>>; + +impl Drop for X { + fn drop(&mut self) { + self.d.borrow_mut().push(*self.x); + } +} + +enum DoubleOption { + Some2(T, U), + _None2, +} + +fn main() { + let d: DropOrderListPtr = <_>::default(); + { + let mk = |v| X { x: Box::new(v), d: d.clone() }; + let check = |a1: &X, a2, b1: &X, b2| { + assert_eq!(*a1.x, a2); + assert_eq!(*b1.x, b2); + }; + + let x = DoubleOption::Some2(mk(1), mk(2)); + match x { + DoubleOption::Some2(ref a, b) => check(a, 1, &b, 2), + DoubleOption::_None2 => panic!(), + } + let x = DoubleOption::Some2(mk(3), mk(4)); + match x { + DoubleOption::Some2(a, ref b) => check(&a, 3, b, 4), + DoubleOption::_None2 => panic!(), + } + match DoubleOption::Some2(mk(5), mk(6)) { + DoubleOption::Some2(ref a, b) => check(a, 5, &b, 6), + DoubleOption::_None2 => panic!(), + } + match DoubleOption::Some2(mk(7), mk(8)) { + DoubleOption::Some2(a, ref b) => check(&a, 7, b, 8), + DoubleOption::_None2 => panic!(), + } + { + let (a, ref b) = (mk(9), mk(10)); + let (ref c, d) = (mk(11), mk(12)); + check(&a, 9, b, 10); + check(c, 11, &d, 12); + } + fn fun([a, ref mut b, ref xs @ .., ref c, d]: [X; 6]) { + assert_eq!(*a.x, 13); + assert_eq!(*b.x, 14); + assert_eq!(&[*xs[0].x, *xs[1].x], &[15, 16]); + assert_eq!(*c.x, 17); + assert_eq!(*d.x, 18); + } + fun([mk(13), mk(14), mk(15), mk(16), mk(17), mk(18)]); + + let lam = |(a, ref b, c, ref mut d): (X, X, X, X)| { + assert_eq!(*a.x, 19); + assert_eq!(*b.x, 20); + assert_eq!(*c.x, 21); + assert_eq!(*d.x, 22); + }; + lam((mk(19), mk(20), mk(21), mk(22))); + } + let expected = [2, 3, 6, 5, 7, 8, 12, 11, 9, 10, 18, 13, 14, 15, 16, 17, 21, 19, 20, 22, 4, 1]; + assert_eq!(&*d.borrow(), &expected); +} diff --git a/src/test/ui/pattern/rest-pat-semantic-disallowed.rs b/src/test/ui/pattern/rest-pat-semantic-disallowed.rs index 31620216e82e1..84552f2e73315 100644 --- a/src/test/ui/pattern/rest-pat-semantic-disallowed.rs +++ b/src/test/ui/pattern/rest-pat-semantic-disallowed.rs @@ -2,7 +2,7 @@ // outside of slice (+ ident patterns witin those), tuple, // and tuple struct patterns and that duplicates are caught in these contexts. -#![feature(slice_patterns, box_patterns)] +#![feature(box_patterns)] fn main() {} diff --git a/src/test/ui/rfc-2005-default-binding-mode/for.rs b/src/test/ui/rfc-2005-default-binding-mode/for.rs index 3bf053eb874ce..aa42c7bb9c2f1 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/for.rs +++ b/src/test/ui/rfc-2005-default-binding-mode/for.rs @@ -1,10 +1,11 @@ +#![feature(move_ref_pattern)] + struct Foo {} pub fn main() { - let mut tups = vec![(Foo{}, Foo{})]; + let mut tups = vec![(Foo {}, Foo {})]; // The below desugars to &(ref n, mut m). for (n, mut m) in &tups { - //~^ ERROR cannot bind by-move and by-ref in the same pattern - //~| ERROR cannot move out of a shared reference + //~^ ERROR cannot move out of a shared reference } } 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 ebc6ff5d8c3fe..ef62431388081 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/for.stderr +++ b/src/test/ui/rfc-2005-default-binding-mode/for.stderr @@ -1,13 +1,5 @@ -error[E0009]: cannot bind by-move and by-ref in the same pattern - --> $DIR/for.rs:6:13 - | -LL | for (n, mut m) in &tups { - | - ^^^^^ by-move pattern here - | | - | by-ref pattern here - error[E0507]: cannot move out of a shared reference - --> $DIR/for.rs:6:23 + --> $DIR/for.rs:8:23 | LL | for (n, mut m) in &tups { | ----- ^^^^^ @@ -15,7 +7,6 @@ LL | for (n, mut m) in &tups { | data moved here | move occurs because `m` has type `Foo`, which does not implement the `Copy` trait -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0009, E0507. -For more information about an error, try `rustc --explain E0009`. +For more information about this error, try `rustc --explain E0507`.