Skip to content

Commit 2931c21

Browse files
committed
syntax: do not panic if find enum or struct but find ident
Closes #22426 Closes #22589 Closes #22665 Closes #22712
1 parent f0f7ca2 commit 2931c21

File tree

3 files changed

+79
-45
lines changed

3 files changed

+79
-45
lines changed

src/libsyntax/parse/parser.rs

+37-45
Original file line numberDiff line numberDiff line change
@@ -3505,52 +3505,44 @@ impl<'a> Parser<'a> {
35053505
self.bump();
35063506
pat = PatStruct(enum_path, fields, etc);
35073507
}
3508-
_ => {
3509-
let mut args: Vec<P<Pat>> = Vec::new();
3510-
match self.token {
3511-
token::OpenDelim(token::Paren) => {
3512-
let is_dotdot = self.look_ahead(1, |t| {
3513-
match *t {
3514-
token::DotDot => true,
3515-
_ => false,
3516-
}
3517-
});
3518-
if is_dotdot {
3519-
// This is a "top constructor only" pat
3520-
self.bump();
3521-
self.bump();
3522-
self.expect(&token::CloseDelim(token::Paren));
3523-
pat = PatEnum(enum_path, None);
3524-
} else {
3525-
args = self.parse_enum_variant_seq(
3526-
&token::OpenDelim(token::Paren),
3527-
&token::CloseDelim(token::Paren),
3528-
seq_sep_trailing_allowed(token::Comma),
3529-
|p| p.parse_pat()
3530-
);
3531-
pat = PatEnum(enum_path, Some(args));
3508+
token::OpenDelim(token::Paren) => {
3509+
let is_dotdot = self.look_ahead(1, |t| {
3510+
match *t {
3511+
token::DotDot => true,
3512+
_ => false,
35323513
}
3533-
},
3534-
_ => {
3535-
if !enum_path.global &&
3536-
enum_path.segments.len() == 1 &&
3537-
enum_path.segments[0].parameters.is_empty()
3538-
{
3539-
// NB: If enum_path is a single identifier,
3540-
// this should not be reachable due to special
3541-
// handling further above.
3542-
//
3543-
// However, previously a PatIdent got emitted
3544-
// here, so we preserve the branch just in case.
3545-
//
3546-
// A rewrite of the logic in this function
3547-
// would probably make this obvious.
3548-
self.span_bug(enum_path.span,
3549-
"ident only path should have been covered already");
3550-
} else {
3551-
pat = PatEnum(enum_path, Some(args));
3552-
}
3553-
}
3514+
});
3515+
if is_dotdot {
3516+
// This is a "top constructor only" pat
3517+
self.bump();
3518+
self.bump();
3519+
self.expect(&token::CloseDelim(token::Paren));
3520+
pat = PatEnum(enum_path, None);
3521+
} else {
3522+
let args = self.parse_enum_variant_seq(
3523+
&token::OpenDelim(token::Paren),
3524+
&token::CloseDelim(token::Paren),
3525+
seq_sep_trailing_allowed(token::Comma),
3526+
|p| p.parse_pat()
3527+
);
3528+
pat = PatEnum(enum_path, Some(args));
3529+
}
3530+
}
3531+
_ => {
3532+
if !enum_path.global &&
3533+
enum_path.segments.len() == 1 &&
3534+
enum_path.segments[0].parameters.is_empty()
3535+
{
3536+
// We expect an identifier, but due to
3537+
// `can_be_enum_or_struct` is true above,
3538+
// we reach here instead.
3539+
let tok_str = pprust::path_to_string(&enum_path);
3540+
self.span_fatal(
3541+
enum_path.span,
3542+
&format!("expected identifier, found enum or struct `{}`",
3543+
tok_str));
3544+
} else {
3545+
pat = PatEnum(enum_path, Some(Vec::new()));
35543546
}
35553547
}
35563548
}

src/test/parse-fail/issue-22426.rs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2015 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+
11+
pub struct Foo<T>(T, T);
12+
13+
impl<T> Foo<T> {
14+
fn foo(&self) {
15+
match *self {
16+
// The error message is not ideal in this case, can we do
17+
// better here?
18+
Foo<T>(ref x, ref y) => {} //~ ERROR expected identifier, found enum or struct
19+
}
20+
}
21+
}
22+
23+
fn main() {}

src/test/parse-fail/issue-22712.rs

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2015 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+
11+
struct Foo<B> {
12+
buffer: B
13+
}
14+
15+
fn bar() {
16+
let Foo<Vec<u8>> //~ ERROR expected identifier, found enum or struct
17+
}
18+
19+
fn main() {}

0 commit comments

Comments
 (0)