Add error reporting on nested keywords inside 'enum' definition
This commit is contained in:
parent
a449535bbc
commit
0e660d8a79
3 changed files with 70 additions and 1 deletions
|
@ -9,6 +9,7 @@ use syntax::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness
|
||||||
use syntax::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, ForeignItemKind};
|
use syntax::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, ForeignItemKind};
|
||||||
use syntax::ast::{Ty, TyKind, Generics, TraitRef, EnumDef, VariantData, StructField};
|
use syntax::ast::{Ty, TyKind, Generics, TraitRef, EnumDef, VariantData, StructField};
|
||||||
use syntax::ast::{Mac, MacDelimiter, Block, BindingMode, FnDecl, FnSig, SelfKind, Param};
|
use syntax::ast::{Mac, MacDelimiter, Block, BindingMode, FnDecl, FnSig, SelfKind, Param};
|
||||||
|
use syntax::print::pprust;
|
||||||
use syntax::ptr::P;
|
use syntax::ptr::P;
|
||||||
use syntax::ThinVec;
|
use syntax::ThinVec;
|
||||||
use syntax::token;
|
use syntax::token;
|
||||||
|
@ -16,7 +17,7 @@ use syntax::tokenstream::{TokenTree, TokenStream};
|
||||||
use syntax::source_map::{self, respan, Span};
|
use syntax::source_map::{self, respan, Span};
|
||||||
use syntax::struct_span_err;
|
use syntax::struct_span_err;
|
||||||
use syntax_pos::BytePos;
|
use syntax_pos::BytePos;
|
||||||
use syntax_pos::symbol::{kw, sym};
|
use syntax_pos::symbol::{kw, sym, Symbol};
|
||||||
|
|
||||||
use rustc_error_codes::*;
|
use rustc_error_codes::*;
|
||||||
|
|
||||||
|
@ -1341,6 +1342,10 @@ impl<'a> Parser<'a> {
|
||||||
let vlo = self.token.span;
|
let vlo = self.token.span;
|
||||||
|
|
||||||
let vis = self.parse_visibility(FollowedByType::No)?;
|
let vis = self.parse_visibility(FollowedByType::No)?;
|
||||||
|
if !self.recover_nested_adt_item(kw::Enum)? {
|
||||||
|
// Item already parsed, we need to skip this variant.
|
||||||
|
continue
|
||||||
|
}
|
||||||
let ident = self.parse_ident()?;
|
let ident = self.parse_ident()?;
|
||||||
|
|
||||||
let struct_def = if self.check(&token::OpenDelim(token::Brace)) {
|
let struct_def = if self.check(&token::OpenDelim(token::Brace)) {
|
||||||
|
@ -1742,6 +1747,36 @@ impl<'a> Parser<'a> {
|
||||||
).emit();
|
).emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks if current token is one of tokens which cannot be nested like `kw::Enum`. In case
|
||||||
|
/// it is, we try to parse the item and report error about nested types.
|
||||||
|
fn recover_nested_adt_item(&mut self, keyword: Symbol) -> PResult<'a, bool> {
|
||||||
|
if self.token.is_keyword(kw::Enum) ||
|
||||||
|
self.token.is_keyword(kw::Struct) ||
|
||||||
|
self.token.is_keyword(kw::Union) {
|
||||||
|
|
||||||
|
let prev_token = self.token.clone();
|
||||||
|
let item = self.parse_item()?;
|
||||||
|
if self.token == token::Comma {
|
||||||
|
self.bump();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut err = self.struct_span_err(
|
||||||
|
prev_token.span,
|
||||||
|
&format!("`{}` definition cannot be nested inside `{}`", pprust::token_to_string(&prev_token), keyword),
|
||||||
|
);
|
||||||
|
err.span_suggestion(
|
||||||
|
item.unwrap().span,
|
||||||
|
&format!("consider creating a new `{}` definition instead of nesting", pprust::token_to_string(&prev_token)),
|
||||||
|
String::new(),
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
err.emit();
|
||||||
|
// We successfully parsed the item but we must inform the caller about nested problem.
|
||||||
|
return Ok(false)
|
||||||
|
}
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
|
||||||
fn mk_item(&self, span: Span, ident: Ident, kind: ItemKind, vis: Visibility,
|
fn mk_item(&self, span: Span, ident: Ident, kind: ItemKind, vis: Visibility,
|
||||||
attrs: Vec<Attribute>) -> P<Item> {
|
attrs: Vec<Attribute>) -> P<Item> {
|
||||||
P(Item {
|
P(Item {
|
||||||
|
|
8
src/test/ui/enum/nested-enum.rs
Normal file
8
src/test/ui/enum/nested-enum.rs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
enum Foo {
|
||||||
|
enum Bar { Baz }, //~ ERROR `enum` definition cannot be nested inside `enum`
|
||||||
|
struct Quux { field: u8 }, //~ ERROR `struct` definition cannot be nested inside `enum`
|
||||||
|
union Wibble { field: u8 }, //~ ERROR `union` definition cannot be nested inside `enum`
|
||||||
|
Bat,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() { }
|
26
src/test/ui/enum/nested-enum.stderr
Normal file
26
src/test/ui/enum/nested-enum.stderr
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
error: `enum` definition cannot be nested inside `enum`
|
||||||
|
--> $DIR/nested-enum.rs:2:5
|
||||||
|
|
|
||||||
|
LL | enum Bar { Baz },
|
||||||
|
| ^^^^------------
|
||||||
|
| |
|
||||||
|
| help: consider creating a new `enum` definition instead of nesting
|
||||||
|
|
||||||
|
error: `struct` definition cannot be nested inside `enum`
|
||||||
|
--> $DIR/nested-enum.rs:3:5
|
||||||
|
|
|
||||||
|
LL | struct Quux { field: u8 },
|
||||||
|
| ^^^^^^-------------------
|
||||||
|
| |
|
||||||
|
| help: consider creating a new `struct` definition instead of nesting
|
||||||
|
|
||||||
|
error: `union` definition cannot be nested inside `enum`
|
||||||
|
--> $DIR/nested-enum.rs:4:5
|
||||||
|
|
|
||||||
|
LL | union Wibble { field: u8 },
|
||||||
|
| ^^^^^---------------------
|
||||||
|
| |
|
||||||
|
| help: consider creating a new `union` definition instead of nesting
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue