Skip to content

Commit 5f92a56

Browse files
committed
Introduce #![feature(bindings_after_at)].
Under the gate, `x @ Some(y)` is allowed. This is subject to various restrictions for soundness.
1 parent a916ac2 commit 5f92a56

38 files changed

+1156
-92
lines changed

src/librustc_feature/active.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,10 @@ declare_features! (
539539
/// Allows the use of `loop` and `while` in constants.
540540
(active, const_loop, "1.41.0", Some(52000), None),
541541

542+
/// Allows bindings in the subpattern of a binding pattern.
543+
/// For example, you can write `x @ Some(y)`.
544+
(active, bindings_after_at, "1.41.0", Some(65490), None),
545+
542546
// -------------------------------------------------------------------------
543547
// feature-group-end: actual feature gates
544548
// -------------------------------------------------------------------------
@@ -554,4 +558,5 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[
554558
sym::or_patterns,
555559
sym::let_chains,
556560
sym::raw_dylib,
561+
sym::bindings_after_at,
557562
];

src/librustc_mir/hair/pattern/check_match.rs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,22 @@ use super::_match::{expand_pattern, is_useful, MatchCheckCtxt, Matrix, PatStack}
44

55
use super::{PatCtxt, PatKind, PatternError};
66

7-
use rustc::lint;
8-
use rustc::session::Session;
9-
use rustc::ty::subst::{InternalSubsts, SubstsRef};
10-
use rustc::ty::{self, Ty, TyCtxt};
11-
use rustc_errors::{Applicability, DiagnosticBuilder};
12-
137
use rustc::hir::def::*;
148
use rustc::hir::def_id::DefId;
159
use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
1610
use rustc::hir::HirId;
1711
use rustc::hir::{self, Pat};
18-
19-
use std::slice;
20-
12+
use rustc::lint;
13+
use rustc::session::Session;
14+
use rustc::ty::subst::{InternalSubsts, SubstsRef};
15+
use rustc::ty::{self, Ty, TyCtxt};
16+
use rustc_error_codes::*;
17+
use rustc_errors::{Applicability, DiagnosticBuilder};
18+
use syntax::feature_gate::feature_err;
19+
use syntax_pos::symbol::sym;
2120
use syntax_pos::{MultiSpan, Span};
2221

23-
use rustc_error_codes::*;
22+
use std::slice;
2423

2524
crate fn check_match(tcx: TyCtxt<'_>, def_id: DefId) {
2625
let body_id = match tcx.hir().as_local_hir_id(def_id) {
@@ -123,7 +122,9 @@ impl PatCtxt<'_, '_> {
123122
impl<'tcx> MatchVisitor<'_, 'tcx> {
124123
fn check_patterns(&mut self, has_guard: bool, pat: &Pat) {
125124
check_legality_of_move_bindings(self, has_guard, pat);
126-
check_legality_of_bindings_in_at_patterns(self, pat);
125+
if !self.tcx.features().bindings_after_at {
126+
check_legality_of_bindings_in_at_patterns(self, pat);
127+
}
127128
}
128129

129130
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<'_, '_, '_> {
656657
match pat.kind {
657658
hir::PatKind::Binding(.., ref subpat) => {
658659
if !self.bindings_allowed {
659-
struct_span_err!(
660-
self.cx.tcx.sess,
660+
feature_err(
661+
&self.cx.tcx.sess.parse_sess,
662+
sym::bindings_after_at,
661663
pat.span,
662-
E0303,
663-
"pattern bindings are not allowed after an `@`"
664+
"pattern bindings after an `@` are unstable",
664665
)
665-
.span_label(pat.span, "not allowed after `@`")
666666
.emit();
667667
}
668668

src/librustc_parse/parser/pat.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,7 @@ impl<'a> Parser<'a> {
406406
if let PatKind::Ident(_, _, ref mut sub @ None) = rhs.kind {
407407
// The user inverted the order, so help them fix that.
408408
let mut applicability = Applicability::MachineApplicable;
409+
// FIXME(bindings_after_at): Remove this code when stabilizing the feature.
409410
lhs.walk(&mut |p| match p.kind {
410411
// `check_match` is unhappy if the subpattern has a binding anywhere.
411412
PatKind::Ident(..) => {

src/libsyntax_pos/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ symbols! {
165165
bench,
166166
bin,
167167
bind_by_move_pattern_guards,
168+
bindings_after_at,
168169
block,
169170
bool,
170171
borrowck_graphviz_postflow,

src/test/ui/error-codes/E0007.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
#![feature(bindings_after_at)]
2+
//~^ WARN the feature `bindings_after_at` is incomplete and may cause the compiler to crash
3+
14
fn main() {
25
let x = Some("s".to_string());
36
match x {
47
op_string @ Some(s) => {},
58
//~^ ERROR E0007
6-
//~| ERROR E0303
79
//~| ERROR E0382
810
None => {},
911
}

src/test/ui/error-codes/E0007.stderr

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
1-
error[E0007]: cannot bind by-move with sub-bindings
2-
--> $DIR/E0007.rs:4:9
1+
warning: the feature `bindings_after_at` is incomplete and may cause the compiler to crash
2+
--> $DIR/E0007.rs:1:12
33
|
4-
LL | op_string @ Some(s) => {},
5-
| ^^^^^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it
4+
LL | #![feature(bindings_after_at)]
5+
| ^^^^^^^^^^^^^^^^^
6+
|
7+
= note: `#[warn(incomplete_features)]` on by default
68

7-
error[E0303]: pattern bindings are not allowed after an `@`
8-
--> $DIR/E0007.rs:4:26
9+
error[E0007]: cannot bind by-move with sub-bindings
10+
--> $DIR/E0007.rs:7:9
911
|
1012
LL | op_string @ Some(s) => {},
11-
| ^ not allowed after `@`
13+
| ^^^^^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it
1214

1315
error[E0382]: use of moved value
14-
--> $DIR/E0007.rs:4:26
16+
--> $DIR/E0007.rs:7:26
1517
|
1618
LL | let x = Some("s".to_string());
1719
| - 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) => {},
2224
| | value used here after move
2325
| value moved here
2426

25-
error: aborting due to 3 previous errors
27+
error: aborting due to 2 previous errors
2628

27-
Some errors have detailed explanations: E0007, E0303, E0382.
29+
Some errors have detailed explanations: E0007, E0382.
2830
For more information about an error, try `rustc --explain E0007`.

src/test/ui/error-codes/E0303.rs

Lines changed: 0 additions & 8 deletions
This file was deleted.

src/test/ui/error-codes/E0303.stderr

Lines changed: 0 additions & 19 deletions
This file was deleted.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#![feature(bindings_after_at)]
2+
//~^ WARN the feature `bindings_after_at` is incomplete and may cause the compiler to crash
3+
4+
struct X { x: () }
5+
6+
fn main() {
7+
let x = Some(X { x: () });
8+
match x {
9+
Some(ref _y @ _z) => { }, //~ ERROR cannot bind by-move and by-ref in the same pattern
10+
None => panic!()
11+
}
12+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
warning: the feature `bindings_after_at` is incomplete and may cause the compiler to crash
2+
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:1:12
3+
|
4+
LL | #![feature(bindings_after_at)]
5+
| ^^^^^^^^^^^^^^^^^
6+
|
7+
= note: `#[warn(incomplete_features)]` on by default
8+
9+
error[E0009]: cannot bind by-move and by-ref in the same pattern
10+
--> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:9:23
11+
|
12+
LL | Some(ref _y @ _z) => { },
13+
| ---------^^
14+
| | |
15+
| | by-move pattern here
16+
| both by-ref and by-move used
17+
18+
error: aborting due to previous error
19+
20+
For more information about this error, try `rustc --explain E0009`.

0 commit comments

Comments
 (0)