Provide specific label for patern parsing error

This commit is contained in:
Esteban Küber 2018-10-28 11:54:31 -07:00
parent d491734b15
commit adb96ec64b
11 changed files with 40 additions and 44 deletions

View file

@ -1030,7 +1030,7 @@ impl<'a> Parser<'a> {
} }
}, },
AstFragmentKind::Ty => AstFragment::Ty(self.parse_ty()?), AstFragmentKind::Ty => AstFragment::Ty(self.parse_ty()?),
AstFragmentKind::Pat => AstFragment::Pat(self.parse_pat()?), AstFragmentKind::Pat => AstFragment::Pat(self.parse_pat(None)?),
}) })
} }

View file

@ -419,7 +419,7 @@ pub fn parse_item_panic(parser: &mut Parser) -> Option<P<Item>> {
} }
pub fn parse_pat_panic(parser: &mut Parser) -> P<Pat> { pub fn parse_pat_panic(parser: &mut Parser) -> P<Pat> {
panictry!(parser.parse_pat()) panictry!(parser.parse_pat(None))
} }
pub fn parse_arm_panic(parser: &mut Parser) -> Arm { pub fn parse_arm_panic(parser: &mut Parser) -> Arm {

View file

@ -881,7 +881,7 @@ fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal {
FatalError.raise(); FatalError.raise();
} }
}, },
"pat" => token::NtPat(panictry!(p.parse_pat())), "pat" => token::NtPat(panictry!(p.parse_pat(None))),
"expr" => token::NtExpr(panictry!(p.parse_expr())), "expr" => token::NtExpr(panictry!(p.parse_expr())),
"literal" => token::NtLiteral(panictry!(p.parse_literal_maybe_minus())), "literal" => token::NtLiteral(panictry!(p.parse_literal_maybe_minus())),
"ty" => token::NtTy(panictry!(p.parse_ty())), "ty" => token::NtTy(panictry!(p.parse_ty())),

View file

@ -1827,10 +1827,7 @@ impl<'a> Parser<'a> {
debug!("parse_arg_general parse_pat (require_name:{})", debug!("parse_arg_general parse_pat (require_name:{})",
require_name); require_name);
self.eat_incorrect_doc_comment("method arguments"); self.eat_incorrect_doc_comment("method arguments");
let pat = self.parse_pat().map_err(|mut err| { let pat = self.parse_pat(Some("argument name"))?;
err.span_label(self.span, "expected argument name");
err
})?;
if let Err(mut err) = self.expect(&token::Colon) { if let Err(mut err) = self.expect(&token::Colon) {
// If we find a pattern followed by an identifier, it could be an (incorrect) // If we find a pattern followed by an identifier, it could be an (incorrect)
@ -1879,7 +1876,7 @@ impl<'a> Parser<'a> {
// Recover from attempting to parse the argument as a type without pattern. // Recover from attempting to parse the argument as a type without pattern.
err.cancel(); err.cancel();
mem::replace(self, parser_snapshot_before_ty); mem::replace(self, parser_snapshot_before_ty);
let pat = self.parse_pat()?; let pat = self.parse_pat(Some("argument name"))?;
self.expect(&token::Colon)?; self.expect(&token::Colon)?;
let ty = self.parse_ty()?; let ty = self.parse_ty()?;
@ -1917,7 +1914,7 @@ impl<'a> Parser<'a> {
/// Parse an argument in a lambda header e.g. |arg, arg| /// Parse an argument in a lambda header e.g. |arg, arg|
fn parse_fn_block_arg(&mut self) -> PResult<'a, Arg> { fn parse_fn_block_arg(&mut self) -> PResult<'a, Arg> {
let pat = self.parse_pat()?; let pat = self.parse_pat(Some("argument name"))?;
let t = if self.eat(&token::Colon) { let t = if self.eat(&token::Colon) {
self.parse_ty()? self.parse_ty()?
} else { } else {
@ -3784,7 +3781,7 @@ impl<'a> Parser<'a> {
"`..` can only be used once per tuple or tuple struct pattern"); "`..` can only be used once per tuple or tuple struct pattern");
} }
} else if !self.check(&token::CloseDelim(token::Paren)) { } else if !self.check(&token::CloseDelim(token::Paren)) {
fields.push(self.parse_pat()?); fields.push(self.parse_pat(None)?);
} else { } else {
break break
} }
@ -3840,7 +3837,7 @@ impl<'a> Parser<'a> {
} }
} }
let subpat = self.parse_pat()?; let subpat = self.parse_pat(None)?;
if before_slice && self.eat(&token::DotDot) { if before_slice && self.eat(&token::DotDot) {
slice = Some(subpat); slice = Some(subpat);
before_slice = false; before_slice = false;
@ -3865,7 +3862,7 @@ impl<'a> Parser<'a> {
// Parsing a pattern of the form "fieldname: pat" // Parsing a pattern of the form "fieldname: pat"
let fieldname = self.parse_field_name()?; let fieldname = self.parse_field_name()?;
self.bump(); self.bump();
let pat = self.parse_pat()?; let pat = self.parse_pat(None)?;
hi = pat.span; hi = pat.span;
(pat, fieldname, false) (pat, fieldname, false)
} else { } else {
@ -4067,7 +4064,7 @@ impl<'a> Parser<'a> {
/// "top-level" patterns in a match arm, `for` loop, `let`, &c. (in contrast /// "top-level" patterns in a match arm, `for` loop, `let`, &c. (in contrast
/// to subpatterns within such). /// to subpatterns within such).
fn parse_top_level_pat(&mut self) -> PResult<'a, P<Pat>> { fn parse_top_level_pat(&mut self) -> PResult<'a, P<Pat>> {
let pat = self.parse_pat()?; let pat = self.parse_pat(None)?;
if self.token == token::Comma { if self.token == token::Comma {
// An unexpected comma after a top-level pattern is a clue that the // An unexpected comma after a top-level pattern is a clue that the
// user (perhaps more accustomed to some other language) forgot the // user (perhaps more accustomed to some other language) forgot the
@ -4099,13 +4096,17 @@ impl<'a> Parser<'a> {
} }
/// Parse a pattern. /// Parse a pattern.
pub fn parse_pat(&mut self) -> PResult<'a, P<Pat>> { pub fn parse_pat(&mut self, expected: Option<&'static str>) -> PResult<'a, P<Pat>> {
self.parse_pat_with_range_pat(true) self.parse_pat_with_range_pat(true, expected)
} }
/// Parse a pattern, with a setting whether modern range patterns e.g. `a..=b`, `a..b` are /// Parse a pattern, with a setting whether modern range patterns e.g. `a..=b`, `a..b` are
/// allowed. /// allowed.
fn parse_pat_with_range_pat(&mut self, allow_range_pat: bool) -> PResult<'a, P<Pat>> { fn parse_pat_with_range_pat(
&mut self,
allow_range_pat: bool,
expected: Option<&'static str>,
) -> PResult<'a, P<Pat>> {
maybe_whole!(self, NtPat, |x| x); maybe_whole!(self, NtPat, |x| x);
let lo = self.span; let lo = self.span;
@ -4121,7 +4122,7 @@ impl<'a> Parser<'a> {
err.span_label(self.span, "unexpected lifetime"); err.span_label(self.span, "unexpected lifetime");
return Err(err); return Err(err);
} }
let subpat = self.parse_pat_with_range_pat(false)?; let subpat = self.parse_pat_with_range_pat(false, expected)?;
pat = PatKind::Ref(subpat, mutbl); pat = PatKind::Ref(subpat, mutbl);
} }
token::OpenDelim(token::Paren) => { token::OpenDelim(token::Paren) => {
@ -4167,7 +4168,7 @@ impl<'a> Parser<'a> {
pat = self.parse_pat_ident(BindingMode::ByRef(mutbl))?; pat = self.parse_pat_ident(BindingMode::ByRef(mutbl))?;
} else if self.eat_keyword(keywords::Box) { } else if self.eat_keyword(keywords::Box) {
// Parse box pat // Parse box pat
let subpat = self.parse_pat_with_range_pat(false)?; let subpat = self.parse_pat_with_range_pat(false, None)?;
pat = PatKind::Box(subpat); pat = PatKind::Box(subpat);
} else if self.token.is_ident() && !self.token.is_reserved_ident() && } else if self.token.is_ident() && !self.token.is_reserved_ident() &&
self.parse_as_ident() { self.parse_as_ident() {
@ -4267,9 +4268,14 @@ impl<'a> Parser<'a> {
} }
Err(mut err) => { Err(mut err) => {
self.cancel(&mut err); self.cancel(&mut err);
let msg = format!("expected pattern, found {}", self.this_token_descr()); let expected = expected.unwrap_or("pattern");
let msg = format!(
"expected {}, found {}",
expected,
self.this_token_descr(),
);
let mut err = self.fatal(&msg); let mut err = self.fatal(&msg);
err.span_label(self.span, "expected pattern"); err.span_label(self.span, format!("expected {}", expected));
return Err(err); return Err(err);
} }
} }
@ -4313,7 +4319,7 @@ impl<'a> Parser<'a> {
-> PResult<'a, PatKind> { -> PResult<'a, PatKind> {
let ident = self.parse_ident()?; let ident = self.parse_ident()?;
let sub = if self.eat(&token::At) { let sub = if self.eat(&token::At) {
Some(self.parse_pat()?) Some(self.parse_pat(Some("binding pattern"))?)
} else { } else {
None None
}; };

View file

@ -68,7 +68,7 @@ pub fn string_to_item (source_str : String) -> Option<P<ast::Item>> {
pub fn string_to_pat(source_str: String) -> P<ast::Pat> { pub fn string_to_pat(source_str: String) -> P<ast::Pat> {
let ps = ParseSess::new(FilePathMapping::empty()); let ps = ParseSess::new(FilePathMapping::empty());
with_error_checking_parse(source_str, &ps, |p| { with_error_checking_parse(source_str, &ps, |p| {
p.parse_pat() p.parse_pat(None)
}) })
} }

View file

@ -11,5 +11,6 @@
// compile-flags: -Z parse-only // compile-flags: -Z parse-only
impl S { impl S {
fn f(*, a: u8) -> u8 {} //~ ERROR expected pattern, found `*` fn f(*, a: u8) -> u8 {}
//~^ ERROR expected argument name, found `*`
} }

View file

@ -1,11 +1,8 @@
error: expected pattern, found `*` error: expected argument name, found `*`
--> $DIR/issue-33413.rs:14:10 --> $DIR/issue-33413.rs:14:10
| |
LL | fn f(*, a: u8) -> u8 {} //~ ERROR expected pattern, found `*` LL | fn f(*, a: u8) -> u8 {}
| ^ | ^ expected argument name
| |
| expected pattern
| expected argument name
error: aborting due to previous error error: aborting due to previous error

View file

@ -2,10 +2,7 @@ error: unexpected lifetime `'a` in pattern
--> $DIR/lifetime-in-pattern.rs:13:10 --> $DIR/lifetime-in-pattern.rs:13:10
| |
LL | fn test(&'a str) { LL | fn test(&'a str) {
| ^^ | ^^ unexpected lifetime
| |
| unexpected lifetime
| expected argument name
error: aborting due to previous error error: aborting due to previous error

View file

@ -10,4 +10,5 @@
// compile-flags: -Z parse-only // compile-flags: -Z parse-only
fn f(+x: isize) {} //~ ERROR expected pattern, found `+` fn f(+x: isize) {}
//~^ ERROR expected argument name, found `+`

View file

@ -1,11 +1,8 @@
error: expected pattern, found `+` error: expected argument name, found `+`
--> $DIR/removed-syntax-mode.rs:13:6 --> $DIR/removed-syntax-mode.rs:13:6
| |
LL | fn f(+x: isize) {} //~ ERROR expected pattern, found `+` LL | fn f(+x: isize) {}
| ^ | ^ expected argument name
| |
| expected pattern
| expected argument name
error: aborting due to previous error error: aborting due to previous error

View file

@ -2,10 +2,7 @@ error: unexpected lifetime `'a` in pattern
--> $DIR/self-vs-path-ambiguity.rs:19:11 --> $DIR/self-vs-path-ambiguity.rs:19:11
| |
LL | fn i(&'a self::S: &S) {} //~ ERROR unexpected lifetime `'a` in pattern LL | fn i(&'a self::S: &S) {} //~ ERROR unexpected lifetime `'a` in pattern
| ^^ | ^^ unexpected lifetime
| |
| unexpected lifetime
| expected argument name
error: aborting due to previous error error: aborting due to previous error