Skip to content

Commit d837213

Browse files
committed
Fixes #21033 with accompanying test.
1 parent 89c4e37 commit d837213

File tree

3 files changed

+87
-26
lines changed

3 files changed

+87
-26
lines changed

src/libsyntax/parse/parser.rs

+34-25
Original file line numberDiff line numberDiff line change
@@ -3256,39 +3256,48 @@ impl<'a> Parser<'a> {
32563256
break;
32573257
}
32583258

3259-
let bind_type = if self.eat_keyword(keywords::Mut) {
3260-
BindByValue(MutMutable)
3261-
} else if self.eat_keyword(keywords::Ref) {
3262-
BindByRef(self.parse_mutability())
3263-
} else {
3264-
BindByValue(MutImmutable)
3265-
};
3266-
3267-
let fieldname = self.parse_ident();
3268-
3269-
let (subpat, is_shorthand) = if self.check(&token::Colon) {
3270-
match bind_type {
3271-
BindByRef(..) | BindByValue(MutMutable) => {
3272-
let token_str = self.this_token_to_string();
3273-
self.fatal(&format!("unexpected `{}`",
3274-
token_str)[])
3275-
}
3276-
_ => {}
3277-
}
3278-
3259+
// Check if a colon exists one ahead. This means we're parsing a fieldname.
3260+
let (subpat, fieldname, is_shorthand) = if self.look_ahead(1, |t| t == &token::Colon) {
3261+
// Parsing a pattern of the form "fieldname: pat"
3262+
let fieldname = self.parse_ident();
32793263
self.bump();
32803264
let pat = self.parse_pat();
32813265
hi = pat.span.hi;
3282-
(pat, false)
3266+
(pat, fieldname, false)
32833267
} else {
3268+
// Parsing a pattern of the form "(box) (ref) (mut) fieldname"
3269+
let is_box = self.eat_keyword(keywords::Box);
3270+
let boxed_span_lo = self.span.lo;
3271+
let is_ref = self.eat_keyword(keywords::Ref);
3272+
let is_mut = self.eat_keyword(keywords::Mut);
3273+
let fieldname = self.parse_ident();
32843274
hi = self.last_span.hi;
3285-
let fieldpath = codemap::Spanned{span:self.last_span, node: fieldname};
3286-
(P(ast::Pat {
3275+
3276+
let bind_type = match (is_ref, is_mut) {
3277+
(true, true) => BindByRef(MutMutable),
3278+
(true, false) => BindByRef(MutImmutable),
3279+
(false, true) => BindByValue(MutMutable),
3280+
(false, false) => BindByValue(MutImmutable),
3281+
};
3282+
let fieldpath = codemap::Spanned{span:self.last_span, node:fieldname};
3283+
let fieldpat = P(ast::Pat{
32873284
id: ast::DUMMY_NODE_ID,
32883285
node: PatIdent(bind_type, fieldpath, None),
3289-
span: self.last_span
3290-
}), true)
3286+
span: mk_sp(boxed_span_lo, hi),
3287+
});
3288+
3289+
let subpat = if is_box {
3290+
P(ast::Pat{
3291+
id: ast::DUMMY_NODE_ID,
3292+
node: PatBox(fieldpat),
3293+
span: mk_sp(lo, hi),
3294+
})
3295+
} else {
3296+
fieldpat
3297+
};
3298+
(subpat, fieldname, true)
32913299
};
3300+
32923301
fields.push(codemap::Spanned { span: mk_sp(lo, hi),
32933302
node: ast::FieldPat { ident: fieldname,
32943303
pat: subpat,

src/test/compile-fail/bind-struct-early-modifiers.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
fn main() {
1212
struct Foo { x: isize }
1313
match (Foo { x: 10 }) {
14-
Foo { ref x: ref x } => {}, //~ ERROR unexpected `:`
14+
Foo { ref x: ref x } => {}, //~ ERROR expected `,`, found `:`
1515
_ => {}
1616
}
1717
}

src/test/run-pass/issue-21033.rs

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
#![feature(box_syntax)]
11+
12+
enum E {
13+
StructVar { boxed: Box<i32> }
14+
}
15+
16+
fn main() {
17+
18+
// Test matching each shorthand notation for field patterns.
19+
let mut a = E::StructVar { boxed: box 3 };
20+
match a {
21+
E::StructVar { box boxed } => { }
22+
}
23+
match a {
24+
E::StructVar { box ref boxed } => { }
25+
}
26+
match a {
27+
E::StructVar { box mut boxed } => { }
28+
}
29+
match a {
30+
E::StructVar { box ref mut boxed } => { }
31+
}
32+
match a {
33+
E::StructVar { ref boxed } => { }
34+
}
35+
match a {
36+
E::StructVar { ref mut boxed } => { }
37+
}
38+
match a {
39+
E::StructVar { mut boxed } => { }
40+
}
41+
42+
// Test matching non shorthand notation. Recreate a since last test
43+
// moved `boxed`
44+
let mut a = E::StructVar { boxed: box 3 };
45+
match a {
46+
E::StructVar { boxed: box ref mut num } => { }
47+
}
48+
match a {
49+
E::StructVar { boxed: ref mut num } => { }
50+
}
51+
52+
}

0 commit comments

Comments
 (0)