Introduce #![feature(bindings_after_at)].

Under the gate, `x @ Some(y)` is allowed.
This is subject to various restrictions for soundness.
This commit is contained in:
Mazdak Farrokhzad 2019-11-11 11:39:52 +01:00
parent a916ac22b9
commit 5f92a56ed6
38 changed files with 1156 additions and 92 deletions

View file

@ -539,6 +539,10 @@ declare_features! (
/// Allows the use of `loop` and `while` in constants.
(active, const_loop, "1.41.0", Some(52000), None),
/// Allows bindings in the subpattern of a binding pattern.
/// For example, you can write `x @ Some(y)`.
(active, bindings_after_at, "1.41.0", Some(65490), None),
// -------------------------------------------------------------------------
// feature-group-end: actual feature gates
// -------------------------------------------------------------------------
@ -554,4 +558,5 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[
sym::or_patterns,
sym::let_chains,
sym::raw_dylib,
sym::bindings_after_at,
];

View file

@ -4,23 +4,22 @@ use super::_match::{expand_pattern, is_useful, MatchCheckCtxt, Matrix, PatStack}
use super::{PatCtxt, PatKind, PatternError};
use rustc::lint;
use rustc::session::Session;
use rustc::ty::subst::{InternalSubsts, SubstsRef};
use rustc::ty::{self, Ty, TyCtxt};
use rustc_errors::{Applicability, DiagnosticBuilder};
use rustc::hir::def::*;
use rustc::hir::def_id::DefId;
use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc::hir::HirId;
use rustc::hir::{self, Pat};
use std::slice;
use rustc::lint;
use rustc::session::Session;
use rustc::ty::subst::{InternalSubsts, SubstsRef};
use rustc::ty::{self, Ty, TyCtxt};
use rustc_error_codes::*;
use rustc_errors::{Applicability, DiagnosticBuilder};
use syntax::feature_gate::feature_err;
use syntax_pos::symbol::sym;
use syntax_pos::{MultiSpan, Span};
use rustc_error_codes::*;
use std::slice;
crate fn check_match(tcx: TyCtxt<'_>, def_id: DefId) {
let body_id = match tcx.hir().as_local_hir_id(def_id) {
@ -123,7 +122,9 @@ 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_legality_of_bindings_in_at_patterns(self, pat);
if !self.tcx.features().bindings_after_at {
check_legality_of_bindings_in_at_patterns(self, pat);
}
}
fn check_match(&mut self, scrut: &hir::Expr, arms: &'tcx [hir::Arm], source: hir::MatchSource) {
@ -656,13 +657,12 @@ impl<'v> Visitor<'v> for AtBindingPatternVisitor<'_, '_, '_> {
match pat.kind {
hir::PatKind::Binding(.., ref subpat) => {
if !self.bindings_allowed {
struct_span_err!(
self.cx.tcx.sess,
feature_err(
&self.cx.tcx.sess.parse_sess,
sym::bindings_after_at,
pat.span,
E0303,
"pattern bindings are not allowed after an `@`"
"pattern bindings after an `@` are unstable",
)
.span_label(pat.span, "not allowed after `@`")
.emit();
}

View file

@ -406,6 +406,7 @@ impl<'a> Parser<'a> {
if let PatKind::Ident(_, _, ref mut sub @ None) = rhs.kind {
// The user inverted the order, so help them fix that.
let mut applicability = Applicability::MachineApplicable;
// FIXME(bindings_after_at): Remove this code when stabilizing the feature.
lhs.walk(&mut |p| match p.kind {
// `check_match` is unhappy if the subpattern has a binding anywhere.
PatKind::Ident(..) => {

View file

@ -165,6 +165,7 @@ symbols! {
bench,
bin,
bind_by_move_pattern_guards,
bindings_after_at,
block,
bool,
borrowck_graphviz_postflow,

View file

@ -1,9 +1,11 @@
#![feature(bindings_after_at)]
//~^ WARN the feature `bindings_after_at` is incomplete and may cause the compiler to crash
fn main() {
let x = Some("s".to_string());
match x {
op_string @ Some(s) => {},
//~^ ERROR E0007
//~| ERROR E0303
//~| ERROR E0382
None => {},
}

View file

@ -1,17 +1,19 @@
warning: the feature `bindings_after_at` is incomplete and may cause the compiler to crash
--> $DIR/E0007.rs:1:12
|
LL | #![feature(bindings_after_at)]
| ^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
error[E0007]: cannot bind by-move with sub-bindings
--> $DIR/E0007.rs:4:9
--> $DIR/E0007.rs:7:9
|
LL | op_string @ Some(s) => {},
| ^^^^^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it
error[E0303]: pattern bindings are not allowed after an `@`
--> $DIR/E0007.rs:4:26
|
LL | op_string @ Some(s) => {},
| ^ not allowed after `@`
error[E0382]: use of moved value
--> $DIR/E0007.rs:4:26
--> $DIR/E0007.rs:7:26
|
LL | let x = Some("s".to_string());
| - move occurs because `x` has type `std::option::Option<std::string::String>`, which does not implement the `Copy` trait
@ -22,7 +24,7 @@ LL | op_string @ Some(s) => {},
| | value used here after move
| value moved here
error: aborting due to 3 previous errors
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0007, E0303, E0382.
Some errors have detailed explanations: E0007, E0382.
For more information about an error, try `rustc --explain E0007`.

View file

@ -1,8 +0,0 @@
fn main() {
match Some("hi".to_string()) {
ref op_string_ref @ Some(s) => {},
//~^ ERROR pattern bindings are not allowed after an `@` [E0303]
//~| ERROR E0009
None => {},
}
}

View file

@ -1,19 +0,0 @@
error[E0009]: cannot bind by-move and by-ref in the same pattern
--> $DIR/E0303.rs:3:34
|
LL | ref op_string_ref @ Some(s) => {},
| -------------------------^-
| | |
| | by-move pattern here
| both by-ref and by-move used
error[E0303]: pattern bindings are not allowed after an `@`
--> $DIR/E0303.rs:3:34
|
LL | ref op_string_ref @ Some(s) => {},
| ^ not allowed after `@`
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0009, E0303.
For more information about an error, try `rustc --explain E0009`.

View file

@ -0,0 +1,12 @@
#![feature(bindings_after_at)]
//~^ WARN the feature `bindings_after_at` is incomplete and may cause the compiler to crash
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!()
}
}

View file

@ -0,0 +1,20 @@
warning: the feature `bindings_after_at` is incomplete and may cause the compiler to crash
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:1:12
|
LL | #![feature(bindings_after_at)]
| ^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
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:9:23
|
LL | Some(ref _y @ _z) => { },
| ---------^^
| | |
| | by-move pattern here
| both by-ref and by-move used
error: aborting due to previous error
For more information about this error, try `rustc --explain E0009`.

View file

@ -0,0 +1,15 @@
// See issue #12534.
#![feature(bindings_after_at)]
//~^ WARN the feature `bindings_after_at` is incomplete and may cause the compiler to crash
fn main() {}
struct A(Box<u8>);
fn f(a @ A(u): A) -> Box<u8> {
//~^ ERROR cannot bind by-move with sub-bindings
//~| ERROR use of moved value
drop(a);
u
}

View file

@ -0,0 +1,28 @@
warning: the feature `bindings_after_at` is incomplete and may cause the compiler to crash
--> $DIR/bind-by-move-no-subbindings-fun-param.rs:3:12
|
LL | #![feature(bindings_after_at)]
| ^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
error[E0007]: cannot bind by-move with sub-bindings
--> $DIR/bind-by-move-no-subbindings-fun-param.rs:10:6
|
LL | fn f(a @ A(u): A) -> Box<u8> {
| ^^^^^^^^ 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:10:12
|
LL | fn f(a @ A(u): A) -> Box<u8> {
| ------^-
| | |
| | value used here after move
| value moved here
| move occurs because value has type `A`, which does not implement the `Copy` trait
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0007, E0382.
For more information about an error, try `rustc --explain E0007`.

View file

@ -0,0 +1,24 @@
// Test that moving on both sides of an `@` pattern is not allowed.
#![feature(bindings_after_at)]
//~^ WARN the feature `bindings_after_at` is incomplete and may cause the compiler to crash
fn main() {
struct U; // Not copy!
let a @ b = U;
//~^ ERROR cannot bind by-move with sub-bindings
//~| ERROR use of moved value
let a @ (b, c) = (U, U);
//~^ ERROR cannot bind by-move with sub-bindings
//~| 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
}
}

View file

@ -0,0 +1,76 @@
warning: the feature `bindings_after_at` is incomplete and may cause the compiler to crash
--> $DIR/borrowck-move-and-move.rs:3:12
|
LL | #![feature(bindings_after_at)]
| ^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
error[E0007]: cannot bind by-move with sub-bindings
--> $DIR/borrowck-move-and-move.rs:9: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:13: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:18: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:18:21
|
LL | a @ Ok(b) | a @ Err(b) => {}
| ^^^^^^^^^^ binds an already bound by-move value by moving it
error[E0382]: use of moved value
--> $DIR/borrowck-move-and-move.rs:9:13
|
LL | let a @ b = U;
| ----^ - move occurs because value has type `main::U`, which does not implement the `Copy` trait
| | |
| | value used here after move
| value moved here
error[E0382]: use of moved value
--> $DIR/borrowck-move-and-move.rs:13: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
| | |
| | value used here after move
| value moved here
error[E0382]: use of moved value
--> $DIR/borrowck-move-and-move.rs:18:16
|
LL | match Ok(U) {
| ----- move occurs because value has type `std::result::Result<main::U, main::U>`, which does not implement the `Copy` trait
LL | a @ Ok(b) | a @ Err(b) => {}
| -------^-
| | |
| | value used here after move
| value moved here
error[E0382]: use of moved value
--> $DIR/borrowck-move-and-move.rs:18:29
|
LL | match Ok(U) {
| ----- move occurs because value has type `std::result::Result<main::U, main::U>`, which does not implement the `Copy` trait
LL | a @ Ok(b) | a @ Err(b) => {}
| --------^-
| | |
| | value used here after move
| value moved here
error: aborting due to 8 previous errors
Some errors have detailed explanations: E0007, E0382.
For more information about an error, try `rustc --explain E0007`.

View file

@ -0,0 +1,44 @@
// Test `@` patterns combined with `box` patterns.
#![feature(bindings_after_at)]
//~^ WARN the feature `bindings_after_at` is incomplete and may cause the compiler to crash
#![feature(box_patterns)]
#[derive(Copy, Clone)]
struct C;
fn main() {
let a @ box &b = Box::new(&C);
//~^ ERROR cannot bind by-move with sub-bindings
//~| 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
let ref a @ box b = Box::new(C); // OK; the type is `Copy`.
drop(b);
drop(b);
drop(a);
struct NC;
let ref a @ box b = Box::new(NC); //~ ERROR cannot bind by-move and by-ref in the same pattern
let ref a @ box ref b = Box::new(NC); // OK.
drop(a);
drop(b);
let ref a @ box ref mut b = Box::new(NC); // FIXME: This should not compile.
let ref a @ box ref mut b = Box::new(NC); // FIXME: This should not compile.
*b = NC;
let ref a @ box ref mut b = Box::new(NC);
//~^ 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 `_` as immutable because it is also borrowed as mutable
*a = Box::new(NC);
drop(b);
}

View file

@ -0,0 +1,75 @@
warning: the feature `bindings_after_at` is incomplete and may cause the compiler to crash
--> $DIR/borrowck-pat-at-and-box.rs:3:12
|
LL | #![feature(bindings_after_at)]
| ^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
error[E0007]: cannot bind by-move with sub-bindings
--> $DIR/borrowck-pat-at-and-box.rs:11: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:15:9
|
LL | let a @ box b = Box::new(C);
| ^^^^^^^^^ 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:26:21
|
LL | let ref a @ box b = Box::new(NC);
| ------------^
| | |
| | by-move pattern here
| both by-ref and by-move used
error[E0382]: use of moved value
--> $DIR/borrowck-pat-at-and-box.rs:11: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
| | |
| | value used here after move
| value moved here
error[E0382]: use of moved value
--> $DIR/borrowck-pat-at-and-box.rs:15:17
|
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
| | |
| | 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:35:21
|
LL | let ref a @ box ref mut b = Box::new(NC);
| ------------^^^^^^^^^
| | |
| | mutable borrow occurs here
| immutable borrow occurs here
...
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:40:25
|
LL | let ref mut a @ box ref b = Box::new(NC);
| ----------------^^^^^
| | |
| | immutable borrow occurs here
| mutable borrow occurs here
LL |
LL | *a = Box::new(NC);
| -- mutable borrow later used here
error: aborting due to 7 previous errors
Some errors have detailed explanations: E0007, E0009, E0382, E0502.
For more information about an error, try `rustc --explain E0007`.

View file

@ -0,0 +1,41 @@
// check-pass
// Test `Copy` bindings in the rhs of `@` patterns.
#![feature(slice_patterns)]
#![feature(bindings_after_at)]
//~^ WARN the feature `bindings_after_at` is incomplete and may cause the compiler to crash
#[derive(Copy, Clone)]
struct C;
#[derive(Copy, Clone)]
struct P<A, B>(A, B);
enum E<A, B> { L(A), R(B) }
fn main() {
let a @ b @ c @ d = C;
let a @ (b, c) = (C, C);
let a @ P(b, P(c, d)) = P(C, P(C, C));
let a @ [b, c] = [C, C];
let a @ [b, .., c] = [C, C, C];
let a @ &(b, c) = &(C, C);
let a @ &(b, &P(c, d)) = &(C, &P(C, C));
use self::E::*;
match L(C) {
L(a) | R(a) => {
let a: C = a;
drop(a);
drop(a);
}
}
match R(&L(&C)) {
L(L(&a)) | L(R(&a)) | R(L(&a)) | R(R(&a)) => {
let a: C = a;
drop(a);
drop(a);
}
}
}

View file

@ -0,0 +1,8 @@
warning: the feature `bindings_after_at` is incomplete and may cause the compiler to crash
--> $DIR/borrowck-pat-by-copy-bindings-in-at.rs:6:12
|
LL | #![feature(bindings_after_at)]
| ^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default

View file

@ -0,0 +1,10 @@
#![feature(bindings_after_at)]
//~^ WARN the feature `bindings_after_at` is incomplete and may cause the compiler to crash
fn main() {
match Some("hi".to_string()) {
ref op_string_ref @ Some(s) => {},
//~^ ERROR E0009
None => {},
}
}

View file

@ -0,0 +1,20 @@
warning: the feature `bindings_after_at` is incomplete and may cause the compiler to crash
--> $DIR/borrowck-pat-by-move-and-ref.rs:1:12
|
LL | #![feature(bindings_after_at)]
| ^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
error[E0009]: cannot bind by-move and by-ref in the same pattern
--> $DIR/borrowck-pat-by-move-and-ref.rs:6:34
|
LL | ref op_string_ref @ Some(s) => {},
| -------------------------^-
| | |
| | by-move pattern here
| both by-ref and by-move used
error: aborting due to previous error
For more information about this error, try `rustc --explain E0009`.

View file

@ -0,0 +1,38 @@
// check-pass
// Test that `ref` patterns may be used on both sides
// of an `@` pattern according to NLL borrowck.
#![feature(bindings_after_at)]
//~^ WARN the feature `bindings_after_at` is incomplete and may cause the compiler to crash
fn main() {
struct U; // Not copy!
let ref a @ ref b = U;
let _: &U = a;
let _: &U = b;
let ref a @ (ref b, [ref c, ref d]) = (U, [U, U]);
let _: &(U, [U; 2]) = a;
let _: &U = b;
let _: &U = c;
let _: &U = d;
let a @ (b, [c, d]) = &(U, [U, U]);
let _: &(U, [U; 2]) = a;
let _: &U = b;
let _: &U = c;
let _: &U = d;
let ref a @ &ref b = &U;
let _: &&U = a;
let _: &U = b;
match Ok(U) {
ref a @ Ok(ref b) | ref a @ Err(ref b) => {
let _: &Result<U, U> = a;
let _: &U = b;
}
}
}

View file

@ -0,0 +1,8 @@
warning: the feature `bindings_after_at` is incomplete and may cause the compiler to crash
--> $DIR/borrowck-pat-ref-both-sides.rs:6:12
|
LL | #![feature(bindings_after_at)]
| ^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default

View file

@ -0,0 +1,87 @@
#![feature(bindings_after_at)]
//~^ WARN the feature `bindings_after_at` is incomplete and may cause the compiler to crash
enum Option<T> {
None,
Some(T),
}
fn main() {
match &mut Some(1) {
ref mut z @ &mut Some(ref a) => {
//~^ ERROR cannot borrow `_` as immutable because it is also borrowed as mutable
**z = None;
println!("{}", *a);
}
_ => ()
}
struct U;
let ref a @ ref mut b = U; // FIXME: This should not compile.
let ref mut a @ ref b = U; // FIXME: This should not compile.
let ref a @ (ref mut b, ref mut c) = (U, U); // FIXME: This should not compile.
let ref mut a @ (ref b, ref c) = (U, U); // FIXME: This should not compile.
// FIXME: Seems like we have a soundness hole here.
let ref mut a @ ref b = U;
*a = U; // We are mutating...
drop(b); // ..but at the same time we are holding a live shared borrow.
// FIXME: Inverted; seems like the same issue exists here as well.
let ref a @ ref mut b = U;
*b = U;
drop(a);
match Ok(U) {
ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => {
*a = Err(U); // FIXME: ^ should not compile.
drop(b);
}
}
match Ok(U) {
ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
//~^ 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);
}
}
match Ok(U) {
ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {}
//~^ 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 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 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 move out of `a` in pattern guard
_ => {}
}
let ref a @ (ref mut b, ref mut c) = (U, U);
*b = U; // FIXME: ^ should not compile.
*c = U;
let ref a @ (ref mut b, ref mut c) = (U, U);
//~^ 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);
*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); // FIXME: This should not compile.
}

View file

@ -0,0 +1,128 @@
warning: the feature `bindings_after_at` is incomplete and may cause the compiler to crash
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:1:12
|
LL | #![feature(bindings_after_at)]
| ^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable
--> $DIR/borrowck-pat-ref-mut-and-ref.rs:11:31
|
LL | ref mut z @ &mut Some(ref a) => {
| ----------------------^^^^^-
| | |
| | immutable borrow occurs here
| mutable borrow occurs here
LL |
LL | **z = None;
| ---------- 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:43:20
|
LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
| -----------^^^^^^^^^-
| | |
| | mutable borrow occurs here
| immutable borrow occurs here
...
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:43:45
|
LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
| ------------^^^^^^^^^-
| | |
| | mutable borrow occurs here
| immutable borrow occurs here
...
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:52:61
|
LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {}
| ^^^^^^ cannot assign
|
= 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:57:61
|
LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {}
| ^^^^^^^^^^^ cannot assign
|
= 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:62: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
|
= 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:67: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<main::U, main::U>`, which does not implement the `Copy` trait
|
= 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:76:18
|
LL | let ref a @ (ref mut b, ref mut c) = (U, U);
| ---------^^^^^^^^^------------
| | |
| | mutable borrow occurs here
| immutable borrow occurs here
...
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:76:29
|
LL | let ref a @ (ref mut b, ref mut c) = (U, U);
| --------------------^^^^^^^^^-
| | |
| | mutable borrow occurs here
| immutable borrow occurs here
...
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:82:18
|
LL | let ref a @ (ref mut b, ref mut c) = (U, U);
| ---------^^^^^^^^^------------
| | |
| | mutable borrow occurs here
| immutable borrow occurs here
...
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:82:29
|
LL | let ref a @ (ref mut b, ref mut c) = (U, U);
| --------------------^^^^^^^^^-
| | |
| | mutable borrow occurs here
| immutable borrow occurs here
...
LL | drop(a);
| - immutable borrow later used here
error: aborting due to 11 previous errors
Some errors have detailed explanations: E0502, E0507.
For more information about an error, try `rustc --explain E0502`.

View file

@ -0,0 +1,68 @@
// Test that `ref mut x @ ref mut y` and varieties of that are not allowed.
#![feature(bindings_after_at)]
//~^ WARN the feature `bindings_after_at` is incomplete and may cause the compiler to crash
fn main() {
struct U;
let ref mut a @ ref mut b = U;
//~^ ERROR cannot borrow `_` as mutable more than once at a time
drop(a);
let ref mut a @ ref mut b = U; // FIXME: This should not compile.
drop(b);
let ref mut a @ ref mut b = U; // FIXME: This should not compile.
let ref mut a @ ref mut b = U;
//~^ ERROR cannot borrow `_` as mutable more than once at a time
*a = U;
let ref mut a @ ref mut b = U; // FIXME: This should not compile.
*b = U;
let ref mut a @ (ref mut b, [ref mut c, ref mut d]) = (U, [U, U]);
// FIXME: This should not compile.
let a @ (ref mut b, ref mut c) = (U, U);
//~^ ERROR cannot bind by-move with sub-bindings
//~| 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
let a @ &mut ref mut b = &mut U;
//~^ ERROR cannot bind by-move with sub-bindings
//~| 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
match Ok(U) {
ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
// FIXME: This should not compile.
}
}
match Ok(U) {
ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
*b = U;
// FIXME: This should not compile.
}
}
match Ok(U) {
ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
//~^ 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);
// FIXME: The binding name `_` used above makes for problematic diagnostics.
// Resolve that somehow...
}
}
match Ok(U) {
ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
//~^ ERROR cannot borrow `_` as mutable more than once at a time
//~| ERROR cannot borrow `_` as mutable more than once at a time
drop(a);
}
}
}

View file

@ -0,0 +1,144 @@
warning: the feature `bindings_after_at` is incomplete and may cause the compiler to crash
--> $DIR/borrowck-pat-ref-mut-twice.rs:3:12
|
LL | #![feature(bindings_after_at)]
| ^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
error[E0007]: cannot bind by-move with sub-bindings
--> $DIR/borrowck-pat-ref-mut-twice.rs:25: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:29:9
|
LL | let a @ (b, [c, d]) = &mut val; // Same as ^--
| ^^^^^^^^^^^^^^^ 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:33:9
|
LL | let a @ &mut ref mut b = &mut 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:36:9
|
LL | let a @ &mut (ref mut b, ref mut c) = &mut (U, U);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it
error[E0499]: cannot borrow `_` as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:9:21
|
LL | let ref mut a @ ref mut b = U;
| ------------^^^^^^^^^
| | |
| | second mutable borrow occurs here
| first mutable borrow occurs here
LL |
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:16:21
|
LL | let ref mut a @ ref mut b = U;
| ------------^^^^^^^^^
| | |
| | second mutable borrow occurs here
| first mutable borrow occurs here
LL |
LL | *a = U;
| ------ first borrow later used here
error[E0382]: borrow of moved value
--> $DIR/borrowck-pat-ref-mut-twice.rs:25: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
| | |
| | value borrowed here after move
| value moved here
error[E0382]: borrow of moved value
--> $DIR/borrowck-pat-ref-mut-twice.rs:29: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
| | |
| | value borrowed here after move
| value moved here
error[E0382]: borrow of moved value
--> $DIR/borrowck-pat-ref-mut-twice.rs:33: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
| | |
| | value borrowed here after move
| value moved here
error[E0382]: borrow of moved value
--> $DIR/borrowck-pat-ref-mut-twice.rs:36: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
| | |
| | value borrowed here after move
| value moved here
error[E0499]: cannot borrow `_` as mutable more than once at a time
--> $DIR/borrowck-pat-ref-mut-twice.rs:52:24
|
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
| ---------------^^^^^^^^^-
| | |
| | second mutable borrow occurs here
| first mutable borrow occurs here
...
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:52:53
|
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
| ----------------^^^^^^^^^-
| | |
| | second mutable borrow occurs here
| first mutable borrow occurs here
...
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:62:24
|
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
| ---------------^^^^^^^^^-
| | |
| | second mutable borrow occurs here
| first mutable borrow occurs here
...
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:62:53
|
LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
| ----------------^^^^^^^^^-
| | |
| | second mutable borrow occurs here
| first mutable borrow occurs here
...
LL | drop(a);
| - first borrow later used here
error: aborting due to 14 previous errors
Some errors have detailed explanations: E0007, E0382, E0499.
For more information about an error, try `rustc --explain E0007`.

View file

@ -0,0 +1,21 @@
// Test that mixing `Copy` and non-`Copy` types in `@` patterns is forbidden.
#![feature(bindings_after_at)]
//~^ WARN the feature `bindings_after_at` is incomplete and may cause the compiler to crash
#[derive(Copy, Clone)]
struct C;
struct NC<A, B>(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
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
}

View file

@ -0,0 +1,59 @@
warning: the feature `bindings_after_at` is incomplete and may cause the compiler to crash
--> $DIR/copy-and-move-mixed.rs:3:12
|
LL | #![feature(bindings_after_at)]
| ^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
error[E0007]: cannot bind by-move with sub-bindings
--> $DIR/copy-and-move-mixed.rs:12: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:16: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:16: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:12:19
|
LL | let a @ NC(b, c) = NC(C, C);
| ----------^- -------- move occurs because value has type `NC<C, C>`, which does not implement the `Copy` trait
| | |
| | value used here after move
| value moved here
error[E0382]: use of moved value
--> $DIR/copy-and-move-mixed.rs:16:19
|
LL | let a @ NC(b, c @ NC(d, e)) = NC(C, NC(C, C));
| ----------^^^^^^^^^^^^- --------------- move occurs because value has type `NC<C, NC<C, C>>`, which does not implement the `Copy` trait
| | |
| | value used here after move
| value moved here
error[E0382]: use of moved value
--> $DIR/copy-and-move-mixed.rs:16:29
|
LL | let a @ NC(b, c @ NC(d, e)) = NC(C, NC(C, C));
| ----------^-
| | |
| | value used here after move
| value moved here
|
= note: move occurs because value has type `NC<C, C>`, which does not implement the `Copy` trait
error: aborting due to 6 previous errors
Some errors have detailed explanations: E0007, E0382.
For more information about an error, try `rustc --explain E0007`.

View file

@ -0,0 +1,31 @@
// Ensures the independence of each side in `binding @ subpat`
// determine their binding modes independently of each other.
//
// That is, `binding` does not influence `subpat`.
// This is important because we might want to allow `p1 @ p2`,
// where both `p1` and `p2` are syntactically unrestricted patterns.
// If `binding` is allowed to influence `subpat`,
// this would create problems for the generalization aforementioned.
#![feature(bindings_after_at)]
//~^ WARN the feature `bindings_after_at` is incomplete and may cause the compiler to crash
fn main() {
struct NotCopy;
let a @ b = &NotCopy; // OK
let _: &NotCopy = a;
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
match Ok(NotCopy) {
Ok(ref a @ b) | Err(ref a @ b) => {}
//~^ ERROR cannot bind by-move and by-ref in the same pattern
}
match NotCopy {
ref a @ b => {}
//~^ ERROR cannot bind by-move and by-ref in the same pattern
}
}

View file

@ -0,0 +1,48 @@
warning: the feature `bindings_after_at` is incomplete and may cause the compiler to crash
--> $DIR/default-binding-modes-both-sides-independent.rs:10:12
|
LL | #![feature(bindings_after_at)]
| ^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
error[E0009]: cannot bind by-move and by-ref in the same pattern
--> $DIR/default-binding-modes-both-sides-independent.rs:21:17
|
LL | let ref a @ b = NotCopy;
| --------^
| | |
| | by-move pattern here
| both by-ref and by-move used
error[E0009]: cannot bind by-move and by-ref in the same pattern
--> $DIR/default-binding-modes-both-sides-independent.rs:22:21
|
LL | let ref mut a @ b = NotCopy;
| ------------^
| | |
| | by-move pattern here
| both by-ref and by-move used
error[E0009]: cannot bind by-move and by-ref in the same pattern
--> $DIR/default-binding-modes-both-sides-independent.rs:24:20
|
LL | Ok(ref a @ b) | Err(ref a @ b) => {}
| ^ --------^
| | | |
| | | by-move pattern here
| | both by-ref and by-move used
| by-move pattern here
error[E0009]: cannot bind by-move and by-ref in the same pattern
--> $DIR/default-binding-modes-both-sides-independent.rs:28:17
|
LL | ref a @ b => {}
| --------^
| | |
| | by-move pattern here
| both by-ref and by-move used
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0009`.

View file

@ -0,0 +1,3 @@
fn main() {
let x @ y = 0; //~ ERROR pattern bindings after an `@` are unstable
}

View file

@ -0,0 +1,12 @@
error[E0658]: pattern bindings after an `@` are unstable
--> $DIR/feature-gate-bindings_after_at.rs:2:13
|
LL | let x @ y = 0;
| ^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/65490
= help: add `#![feature(bindings_after_at)]` to the crate attributes to enable
error: aborting due to previous error
For more information about this error, try `rustc --explain E0658`.

View file

@ -0,0 +1,16 @@
// run-pass
#![feature(bindings_after_at)]
//~^ WARN the feature `bindings_after_at` is incomplete and may cause the compiler to crash
struct A { a: u8, b: u8 }
pub fn main() {
match (A { a: 10, b: 20 }) {
ref x @ A { ref a, b: 20 } => {
assert_eq!(x.a, 10);
assert_eq!(*a, 10);
}
A { b: ref _b, .. } => panic!(),
}
}

View file

@ -0,0 +1,8 @@
warning: the feature `bindings_after_at` is incomplete and may cause the compiler to crash
--> $DIR/nested-patterns.rs:3:12
|
LL | #![feature(bindings_after_at)]
| ^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default

View file

@ -0,0 +1,21 @@
// Test that `binding @ subpat` acts as a product context with respect to duplicate binding names.
// The code that is tested here lives in resolve (see `resolve_pattern_inner`).
#![feature(bindings_after_at)]
//~^ WARN the feature `bindings_after_at` is incomplete and may cause the compiler to crash
#![feature(or_patterns)]
//~^ WARN the feature `or_patterns` is incomplete and may cause the compiler to crash
fn main() {
let a @ a @ a = ();
//~^ ERROR identifier `a` is bound more than once in the same pattern
//~| ERROR identifier `a` is bound more than once in the same pattern
let ref a @ ref a = ();
//~^ ERROR identifier `a` is bound more than once in the same pattern
let ref mut a @ ref mut a = ();
//~^ ERROR identifier `a` is bound more than once in the same pattern
let a @ (Ok(a) | Err(a)) = Ok(());
//~^ ERROR identifier `a` is bound more than once in the same pattern
//~| ERROR identifier `a` is bound more than once in the same pattern
}

View file

@ -0,0 +1,53 @@
error[E0416]: identifier `a` is bound more than once in the same pattern
--> $DIR/pat-at-same-name-both.rs:10:13
|
LL | let a @ a @ a = ();
| ^ used in a pattern more than once
error[E0416]: identifier `a` is bound more than once in the same pattern
--> $DIR/pat-at-same-name-both.rs:10:17
|
LL | let a @ a @ a = ();
| ^ used in a pattern more than once
error[E0416]: identifier `a` is bound more than once in the same pattern
--> $DIR/pat-at-same-name-both.rs:13:21
|
LL | let ref a @ ref a = ();
| ^ used in a pattern more than once
error[E0416]: identifier `a` is bound more than once in the same pattern
--> $DIR/pat-at-same-name-both.rs:15:29
|
LL | let ref mut a @ ref mut a = ();
| ^ used in a pattern more than once
error[E0416]: identifier `a` is bound more than once in the same pattern
--> $DIR/pat-at-same-name-both.rs:18:17
|
LL | let a @ (Ok(a) | Err(a)) = Ok(());
| ^ used in a pattern more than once
error[E0416]: identifier `a` is bound more than once in the same pattern
--> $DIR/pat-at-same-name-both.rs:18:26
|
LL | let a @ (Ok(a) | Err(a)) = Ok(());
| ^ used in a pattern more than once
warning: the feature `bindings_after_at` is incomplete and may cause the compiler to crash
--> $DIR/pat-at-same-name-both.rs:4:12
|
LL | #![feature(bindings_after_at)]
| ^^^^^^^^^^^^^^^^^
|
= note: `#[warn(incomplete_features)]` on by default
warning: the feature `or_patterns` is incomplete and may cause the compiler to crash
--> $DIR/pat-at-same-name-both.rs:6:12
|
LL | #![feature(or_patterns)]
| ^^^^^^^^^^^
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0416`.

View file

@ -1,16 +0,0 @@
enum Option<T> {
None,
Some(T),
}
fn main() {
match &mut Some(1) {
ref mut z @ &mut Some(ref a) => {
//~^ ERROR pattern bindings are not allowed after an `@`
//~| ERROR cannot borrow `_` as immutable because it is also borrowed as mutable
**z = None;
println!("{}", *a);
}
_ => ()
}
}

View file

@ -1,22 +0,0 @@
error[E0303]: pattern bindings are not allowed after an `@`
--> $DIR/pattern-bindings-after-at.rs:8:31
|
LL | ref mut z @ &mut Some(ref a) => {
| ^^^^^ not allowed after `@`
error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable
--> $DIR/pattern-bindings-after-at.rs:8:31
|
LL | ref mut z @ &mut Some(ref a) => {
| ----------------------^^^^^-
| | |
| | immutable borrow occurs here
| mutable borrow occurs here
...
LL | **z = None;
| ---------- mutable borrow later used here
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0303, E0502.
For more information about an error, try `rustc --explain E0303`.