Skip to content

Commit eb678ff

Browse files
committed
librustc: Change the syntax of subslice matching to use postfix ..
instead of prefix `..`. This breaks code that looked like: match foo { [ first, ..middle, last ] => { ... } } Change this code to: match foo { [ first, middle.., last ] => { ... } } RFC #55. Closes #16967. [breaking-change]
1 parent 6f34760 commit eb678ff

26 files changed

+110
-82
lines changed

src/doc/rust.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3300,7 +3300,7 @@ it will bind the corresponding slice to the variable. Example:
33003300
fn is_symmetric(list: &[uint]) -> bool {
33013301
match list {
33023302
[] | [_] => true,
3303-
[x, ..inside, y] if x == y => is_symmetric(inside),
3303+
[x, inside.., y] if x == y => is_symmetric(inside),
33043304
_ => false
33053305
}
33063306
}

src/doc/tutorial.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1707,7 +1707,7 @@ let score = match numbers {
17071707
[] => 0,
17081708
[a] => a * 10,
17091709
[a, b] => a * 6 + b * 4,
1710-
[a, b, c, ..rest] => a * 5 + b * 3 + c * 2 + rest.len() as int
1710+
[a, b, c, rest..] => a * 5 + b * 3 + c * 2 + rest.len() as int
17111711
};
17121712
~~~~
17131713

src/librustc/middle/resolve.rs

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1549,18 +1549,13 @@ impl<'a> Resolver<'a> {
15491549
PathListMod { .. } => Some(item.span),
15501550
_ => None
15511551
}).collect::<Vec<Span>>();
1552-
match mod_spans.as_slice() {
1553-
[first, second, ..other] => {
1554-
self.resolve_error(first,
1555-
"`mod` import can only appear once in the list");
1556-
self.session.span_note(second,
1557-
"another `mod` import appears here");
1558-
for &other_span in other.iter() {
1559-
self.session.span_note(other_span,
1560-
"another `mod` import appears here");
1561-
}
1562-
},
1563-
[_] | [] => ()
1552+
if mod_spans.len() > 1 {
1553+
self.resolve_error(mod_spans[0],
1554+
"`mod` import can only appear once in the list");
1555+
for other_span in mod_spans.iter().skip(1) {
1556+
self.session.span_note(*other_span,
1557+
"another `mod` import appears here");
1558+
}
15641559
}
15651560

15661561
for source_item in source_items.iter() {

src/libsyntax/parse/obsolete.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ pub enum ObsoleteSyntax {
3535
ObsoleteManagedType,
3636
ObsoleteManagedExpr,
3737
ObsoleteImportRenaming,
38+
ObsoleteSubsliceMatch,
3839
}
3940

4041
pub trait ParserObsoleteMethods {
@@ -87,6 +88,10 @@ impl<'a> ParserObsoleteMethods for parser::Parser<'a> {
8788
ObsoleteImportRenaming => (
8889
"`use foo = bar` syntax",
8990
"write `use bar as foo` instead"
91+
),
92+
ObsoleteSubsliceMatch => (
93+
"subslice match syntax",
94+
"instead of `..xs`, write `xs..` in a pattern"
9095
)
9196
};
9297

src/libsyntax/parse/parser.rs

Lines changed: 37 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2858,43 +2858,42 @@ impl<'a> Parser<'a> {
28582858
let mut before_slice = true;
28592859

28602860
while self.token != token::RBRACKET {
2861-
if first { first = false; }
2862-
else { self.expect(&token::COMMA); }
2861+
if first {
2862+
first = false;
2863+
} else {
2864+
self.expect(&token::COMMA);
2865+
}
28632866

2864-
let mut is_slice = false;
28652867
if before_slice {
28662868
if self.token == token::DOTDOT {
28672869
self.bump();
2868-
is_slice = true;
2869-
before_slice = false;
2870-
}
2871-
}
28722870

2873-
if is_slice {
2874-
if self.token == token::COMMA || self.token == token::RBRACKET {
2875-
slice = Some(box(GC) ast::Pat {
2876-
id: ast::DUMMY_NODE_ID,
2877-
node: PatWild(PatWildMulti),
2878-
span: self.span,
2879-
})
2880-
} else {
2881-
let subpat = self.parse_pat();
2882-
match *subpat {
2883-
ast::Pat { node: PatIdent(_, _, _), .. } => {
2884-
slice = Some(subpat);
2885-
}
2886-
ast::Pat { span, .. } => self.span_fatal(
2887-
span, "expected an identifier or nothing"
2888-
)
2871+
if self.token == token::COMMA ||
2872+
self.token == token::RBRACKET {
2873+
slice = Some(box(GC) ast::Pat {
2874+
id: ast::DUMMY_NODE_ID,
2875+
node: PatWild(PatWildMulti),
2876+
span: self.span,
2877+
});
2878+
before_slice = false;
2879+
} else {
2880+
let _ = self.parse_pat();
2881+
let span = self.span;
2882+
self.obsolete(span, ObsoleteSubsliceMatch);
28892883
}
2884+
continue
28902885
}
2886+
}
2887+
2888+
let subpat = self.parse_pat();
2889+
if before_slice && self.token == token::DOTDOT {
2890+
self.bump();
2891+
slice = Some(subpat);
2892+
before_slice = false;
2893+
} else if before_slice {
2894+
before.push(subpat);
28912895
} else {
2892-
let subpat = self.parse_pat();
2893-
if before_slice {
2894-
before.push(subpat);
2895-
} else {
2896-
after.push(subpat);
2897-
}
2896+
after.push(subpat);
28982897
}
28992898
}
29002899

@@ -3065,7 +3064,11 @@ impl<'a> Parser<'a> {
30653064
// These expressions are limited to literals (possibly
30663065
// preceded by unary-minus) or identifiers.
30673066
let val = self.parse_literal_maybe_minus();
3068-
if self.eat(&token::DOTDOT) {
3067+
if self.token == token::DOTDOT &&
3068+
self.look_ahead(1, |t| {
3069+
*t != token::COMMA && *t != token::RBRACKET
3070+
}) {
3071+
self.bump();
30693072
let end = if is_ident_or_path(&self.token) {
30703073
let path = self.parse_path(LifetimeAndTypesWithColons)
30713074
.path;
@@ -3106,7 +3109,10 @@ impl<'a> Parser<'a> {
31063109
}
31073110
});
31083111

3109-
if self.look_ahead(1, |t| *t == token::DOTDOT) {
3112+
if self.look_ahead(1, |t| *t == token::DOTDOT) &&
3113+
self.look_ahead(2, |t| {
3114+
*t != token::COMMA && *t != token::RBRACKET
3115+
}) {
31103116
let start = self.parse_expr_res(RESTRICT_NO_BAR_OP);
31113117
self.eat(&token::DOTDOT);
31123118
let end = self.parse_expr_res(RESTRICT_NO_BAR_OP);

src/libsyntax/print/pprust.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1912,13 +1912,13 @@ impl<'a> State<'a> {
19121912
|s, p| s.print_pat(&**p)));
19131913
for p in slice.iter() {
19141914
if !before.is_empty() { try!(self.word_space(",")); }
1915+
try!(self.print_pat(&**p));
19151916
match **p {
19161917
ast::Pat { node: ast::PatWild(ast::PatWildMulti), .. } => {
19171918
// this case is handled by print_pat
19181919
}
19191920
_ => try!(word(&mut self.s, "..")),
19201921
}
1921-
try!(self.print_pat(&**p));
19221922
if !after.is_empty() { try!(self.word_space(",")); }
19231923
}
19241924
try!(self.commasep(Inconsistent,

src/test/compile-fail/borrowck-move-out-of-vec-tail.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub fn main() {
2525
);
2626
let x: &[Foo] = x.as_slice();
2727
match x {
28-
[_, ..tail] => {
28+
[_, tail..] => {
2929
match tail {
3030
[Foo { string: a }, //~ ERROR cannot move out of dereference of `&`-pointer
3131
Foo { string: b }] => {

src/test/compile-fail/borrowck-vec-pattern-element-loan.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ fn a<'a>() -> &'a [int] {
1212
let vec = vec!(1, 2, 3, 4);
1313
let vec: &[int] = vec.as_slice(); //~ ERROR does not live long enough
1414
let tail = match vec {
15-
[_, ..tail] => tail,
15+
[_, tail..] => tail,
1616
_ => fail!("a")
1717
};
1818
tail
@@ -22,7 +22,7 @@ fn b<'a>() -> &'a [int] {
2222
let vec = vec!(1, 2, 3, 4);
2323
let vec: &[int] = vec.as_slice(); //~ ERROR does not live long enough
2424
let init = match vec {
25-
[..init, _] => init,
25+
[init.., _] => init,
2626
_ => fail!("b")
2727
};
2828
init
@@ -32,7 +32,7 @@ fn c<'a>() -> &'a [int] {
3232
let vec = vec!(1, 2, 3, 4);
3333
let vec: &[int] = vec.as_slice(); //~ ERROR does not live long enough
3434
let slice = match vec {
35-
[_, ..slice, _] => slice,
35+
[_, slice.., _] => slice,
3636
_ => fail!("c")
3737
};
3838
slice

src/test/compile-fail/borrowck-vec-pattern-loan-from-mut.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ fn a() {
1212
let mut v = vec!(1, 2, 3);
1313
let vb: &mut [int] = v.as_mut_slice();
1414
match vb {
15-
[_a, ..tail] => {
15+
[_a, tail..] => {
1616
v.push(tail[0] + tail[1]); //~ ERROR cannot borrow
1717
}
1818
_ => {}

src/test/compile-fail/borrowck-vec-pattern-move-tail.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
fn main() {
1212
let mut a = [1i, 2, 3, 4];
1313
let t = match a {
14-
[1, 2, ..tail] => tail,
14+
[1, 2, tail..] => tail,
1515
_ => unreachable!()
1616
};
1717
a[0] = 0; //~ ERROR cannot assign to `a[..]` because it is borrowed

0 commit comments

Comments
 (0)