Skip to content

Commit

Permalink
syntax: do not panic if find enum or struct but find ident
Browse files Browse the repository at this point in the history
Closes #22426
Closes #22589
Closes #22665
Closes #22712
  • Loading branch information
edwardw committed Feb 23, 2015
1 parent f0f7ca2 commit 2931c21
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 45 deletions.
82 changes: 37 additions & 45 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3505,52 +3505,44 @@ impl<'a> Parser<'a> {
self.bump();
pat = PatStruct(enum_path, fields, etc);
}
_ => {
let mut args: Vec<P<Pat>> = Vec::new();
match self.token {
token::OpenDelim(token::Paren) => {
let is_dotdot = self.look_ahead(1, |t| {
match *t {
token::DotDot => true,
_ => false,
}
});
if is_dotdot {
// This is a "top constructor only" pat
self.bump();
self.bump();
self.expect(&token::CloseDelim(token::Paren));
pat = PatEnum(enum_path, None);
} else {
args = self.parse_enum_variant_seq(
&token::OpenDelim(token::Paren),
&token::CloseDelim(token::Paren),
seq_sep_trailing_allowed(token::Comma),
|p| p.parse_pat()
);
pat = PatEnum(enum_path, Some(args));
token::OpenDelim(token::Paren) => {
let is_dotdot = self.look_ahead(1, |t| {
match *t {
token::DotDot => true,
_ => false,
}
},
_ => {
if !enum_path.global &&
enum_path.segments.len() == 1 &&
enum_path.segments[0].parameters.is_empty()
{
// NB: If enum_path is a single identifier,
// this should not be reachable due to special
// handling further above.
//
// However, previously a PatIdent got emitted
// here, so we preserve the branch just in case.
//
// A rewrite of the logic in this function
// would probably make this obvious.
self.span_bug(enum_path.span,
"ident only path should have been covered already");
} else {
pat = PatEnum(enum_path, Some(args));
}
}
});
if is_dotdot {
// This is a "top constructor only" pat
self.bump();
self.bump();
self.expect(&token::CloseDelim(token::Paren));
pat = PatEnum(enum_path, None);
} else {
let args = self.parse_enum_variant_seq(
&token::OpenDelim(token::Paren),
&token::CloseDelim(token::Paren),
seq_sep_trailing_allowed(token::Comma),
|p| p.parse_pat()
);
pat = PatEnum(enum_path, Some(args));
}
}
_ => {
if !enum_path.global &&
enum_path.segments.len() == 1 &&
enum_path.segments[0].parameters.is_empty()
{
// We expect an identifier, but due to
// `can_be_enum_or_struct` is true above,
// we reach here instead.
let tok_str = pprust::path_to_string(&enum_path);
self.span_fatal(
enum_path.span,
&format!("expected identifier, found enum or struct `{}`",
tok_str));
} else {
pat = PatEnum(enum_path, Some(Vec::new()));
}
}
}
Expand Down
23 changes: 23 additions & 0 deletions src/test/parse-fail/issue-22426.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright 2015 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

pub struct Foo<T>(T, T);

impl<T> Foo<T> {
fn foo(&self) {
match *self {
// The error message is not ideal in this case, can we do
// better here?
Foo<T>(ref x, ref y) => {} //~ ERROR expected identifier, found enum or struct
}
}
}

fn main() {}
19 changes: 19 additions & 0 deletions src/test/parse-fail/issue-22712.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright 2015 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

struct Foo<B> {
buffer: B
}

fn bar() {
let Foo<Vec<u8>> //~ ERROR expected identifier, found enum or struct
}

fn main() {}

0 comments on commit 2931c21

Please sign in to comment.