Skip to content

Commit 0e660d8

Browse files
committed
Add error reporting on nested keywords inside 'enum' definition
1 parent a449535 commit 0e660d8

File tree

3 files changed

+70
-1
lines changed

3 files changed

+70
-1
lines changed

src/librustc_parse/parser/item.rs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@ use syntax::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness
99
use syntax::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, ForeignItemKind};
1010
use syntax::ast::{Ty, TyKind, Generics, TraitRef, EnumDef, VariantData, StructField};
1111
use syntax::ast::{Mac, MacDelimiter, Block, BindingMode, FnDecl, FnSig, SelfKind, Param};
12+
use syntax::print::pprust;
1213
use syntax::ptr::P;
1314
use syntax::ThinVec;
1415
use syntax::token;
1516
use syntax::tokenstream::{TokenTree, TokenStream};
1617
use syntax::source_map::{self, respan, Span};
1718
use syntax::struct_span_err;
1819
use syntax_pos::BytePos;
19-
use syntax_pos::symbol::{kw, sym};
20+
use syntax_pos::symbol::{kw, sym, Symbol};
2021

2122
use rustc_error_codes::*;
2223

@@ -1341,6 +1342,10 @@ impl<'a> Parser<'a> {
13411342
let vlo = self.token.span;
13421343

13431344
let vis = self.parse_visibility(FollowedByType::No)?;
1345+
if !self.recover_nested_adt_item(kw::Enum)? {
1346+
// Item already parsed, we need to skip this variant.
1347+
continue
1348+
}
13441349
let ident = self.parse_ident()?;
13451350

13461351
let struct_def = if self.check(&token::OpenDelim(token::Brace)) {
@@ -1742,6 +1747,36 @@ impl<'a> Parser<'a> {
17421747
).emit();
17431748
}
17441749

1750+
/// Checks if current token is one of tokens which cannot be nested like `kw::Enum`. In case
1751+
/// it is, we try to parse the item and report error about nested types.
1752+
fn recover_nested_adt_item(&mut self, keyword: Symbol) -> PResult<'a, bool> {
1753+
if self.token.is_keyword(kw::Enum) ||
1754+
self.token.is_keyword(kw::Struct) ||
1755+
self.token.is_keyword(kw::Union) {
1756+
1757+
let prev_token = self.token.clone();
1758+
let item = self.parse_item()?;
1759+
if self.token == token::Comma {
1760+
self.bump();
1761+
}
1762+
1763+
let mut err = self.struct_span_err(
1764+
prev_token.span,
1765+
&format!("`{}` definition cannot be nested inside `{}`", pprust::token_to_string(&prev_token), keyword),
1766+
);
1767+
err.span_suggestion(
1768+
item.unwrap().span,
1769+
&format!("consider creating a new `{}` definition instead of nesting", pprust::token_to_string(&prev_token)),
1770+
String::new(),
1771+
Applicability::MaybeIncorrect,
1772+
);
1773+
err.emit();
1774+
// We successfully parsed the item but we must inform the caller about nested problem.
1775+
return Ok(false)
1776+
}
1777+
Ok(true)
1778+
}
1779+
17451780
fn mk_item(&self, span: Span, ident: Ident, kind: ItemKind, vis: Visibility,
17461781
attrs: Vec<Attribute>) -> P<Item> {
17471782
P(Item {

src/test/ui/enum/nested-enum.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
enum Foo {
2+
enum Bar { Baz }, //~ ERROR `enum` definition cannot be nested inside `enum`
3+
struct Quux { field: u8 }, //~ ERROR `struct` definition cannot be nested inside `enum`
4+
union Wibble { field: u8 }, //~ ERROR `union` definition cannot be nested inside `enum`
5+
Bat,
6+
}
7+
8+
fn main() { }

src/test/ui/enum/nested-enum.stderr

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
error: `enum` definition cannot be nested inside `enum`
2+
--> $DIR/nested-enum.rs:2:5
3+
|
4+
LL | enum Bar { Baz },
5+
| ^^^^------------
6+
| |
7+
| help: consider creating a new `enum` definition instead of nesting
8+
9+
error: `struct` definition cannot be nested inside `enum`
10+
--> $DIR/nested-enum.rs:3:5
11+
|
12+
LL | struct Quux { field: u8 },
13+
| ^^^^^^-------------------
14+
| |
15+
| help: consider creating a new `struct` definition instead of nesting
16+
17+
error: `union` definition cannot be nested inside `enum`
18+
--> $DIR/nested-enum.rs:4:5
19+
|
20+
LL | union Wibble { field: u8 },
21+
| ^^^^^---------------------
22+
| |
23+
| help: consider creating a new `union` definition instead of nesting
24+
25+
error: aborting due to 3 previous errors
26+

0 commit comments

Comments
 (0)