diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 30cc9836374..f5f01a9e5da 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -3256,39 +3256,48 @@ impl<'a> Parser<'a> { break; } - let bind_type = if self.eat_keyword(keywords::Mut) { - BindByValue(MutMutable) - } else if self.eat_keyword(keywords::Ref) { - BindByRef(self.parse_mutability()) - } else { - BindByValue(MutImmutable) - }; - - let fieldname = self.parse_ident(); - - let (subpat, is_shorthand) = if self.check(&token::Colon) { - match bind_type { - BindByRef(..) | BindByValue(MutMutable) => { - let token_str = self.this_token_to_string(); - self.fatal(&format!("unexpected `{}`", - token_str)[]) - } - _ => {} - } - + // Check if a colon exists one ahead. This means we're parsing a fieldname. + let (subpat, fieldname, is_shorthand) = if self.look_ahead(1, |t| t == &token::Colon) { + // Parsing a pattern of the form "fieldname: pat" + let fieldname = self.parse_ident(); self.bump(); let pat = self.parse_pat(); hi = pat.span.hi; - (pat, false) + (pat, fieldname, false) } else { + // Parsing a pattern of the form "(box) (ref) (mut) fieldname" + let is_box = self.eat_keyword(keywords::Box); + let boxed_span_lo = self.span.lo; + let is_ref = self.eat_keyword(keywords::Ref); + let is_mut = self.eat_keyword(keywords::Mut); + let fieldname = self.parse_ident(); hi = self.last_span.hi; - let fieldpath = codemap::Spanned{span:self.last_span, node: fieldname}; - (P(ast::Pat { + + let bind_type = match (is_ref, is_mut) { + (true, true) => BindByRef(MutMutable), + (true, false) => BindByRef(MutImmutable), + (false, true) => BindByValue(MutMutable), + (false, false) => BindByValue(MutImmutable), + }; + let fieldpath = codemap::Spanned{span:self.last_span, node:fieldname}; + let fieldpat = P(ast::Pat{ id: ast::DUMMY_NODE_ID, node: PatIdent(bind_type, fieldpath, None), - span: self.last_span - }), true) + span: mk_sp(boxed_span_lo, hi), + }); + + let subpat = if is_box { + P(ast::Pat{ + id: ast::DUMMY_NODE_ID, + node: PatBox(fieldpat), + span: mk_sp(lo, hi), + }) + } else { + fieldpat + }; + (subpat, fieldname, true) }; + fields.push(codemap::Spanned { span: mk_sp(lo, hi), node: ast::FieldPat { ident: fieldname, pat: subpat, diff --git a/src/test/compile-fail/bind-struct-early-modifiers.rs b/src/test/compile-fail/bind-struct-early-modifiers.rs index 375f6c5d047..c358a21d125 100644 --- a/src/test/compile-fail/bind-struct-early-modifiers.rs +++ b/src/test/compile-fail/bind-struct-early-modifiers.rs @@ -11,7 +11,7 @@ fn main() { struct Foo { x: isize } match (Foo { x: 10 }) { - Foo { ref x: ref x } => {}, //~ ERROR unexpected `:` + Foo { ref x: ref x } => {}, //~ ERROR expected `,`, found `:` _ => {} } } diff --git a/src/test/run-pass/issue-21033.rs b/src/test/run-pass/issue-21033.rs new file mode 100644 index 00000000000..5dcf1d904d0 --- /dev/null +++ b/src/test/run-pass/issue-21033.rs @@ -0,0 +1,52 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +#![feature(box_syntax)] + +enum E { + StructVar { boxed: Box } +} + +fn main() { + + // Test matching each shorthand notation for field patterns. + let mut a = E::StructVar { boxed: box 3 }; + match a { + E::StructVar { box boxed } => { } + } + match a { + E::StructVar { box ref boxed } => { } + } + match a { + E::StructVar { box mut boxed } => { } + } + match a { + E::StructVar { box ref mut boxed } => { } + } + match a { + E::StructVar { ref boxed } => { } + } + match a { + E::StructVar { ref mut boxed } => { } + } + match a { + E::StructVar { mut boxed } => { } + } + + // Test matching non shorthand notation. Recreate a since last test + // moved `boxed` + let mut a = E::StructVar { boxed: box 3 }; + match a { + E::StructVar { boxed: box ref mut num } => { } + } + match a { + E::StructVar { boxed: ref mut num } => { } + } + +}