diff options
| author | Janusz Marcinkiewicz <virrages@gmail.com> | 2019-11-23 03:41:12 +0100 |
|---|---|---|
| committer | Janusz Marcinkiewicz <virrages@gmail.com> | 2019-11-23 03:41:12 +0100 |
| commit | 0e660d8a79062ba3c664822a72ae782cb8c38da7 (patch) | |
| tree | 7f968a5aa46311dad16b9ae0acb968279720228f | |
| parent | a449535bbc7912c4adc1bbf2ab2738d0442f212c (diff) | |
| download | rust-0e660d8a79062ba3c664822a72ae782cb8c38da7.tar.gz rust-0e660d8a79062ba3c664822a72ae782cb8c38da7.zip | |
Add error reporting on nested keywords inside 'enum' definition
| -rw-r--r-- | src/librustc_parse/parser/item.rs | 37 | ||||
| -rw-r--r-- | src/test/ui/enum/nested-enum.rs | 8 | ||||
| -rw-r--r-- | src/test/ui/enum/nested-enum.stderr | 26 |
3 files changed, 70 insertions, 1 deletions
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 13645e7144a..712715705e1 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -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::{Ty, TyKind, Generics, TraitRef, EnumDef, VariantData, StructField}; use syntax::ast::{Mac, MacDelimiter, Block, BindingMode, FnDecl, FnSig, SelfKind, Param}; +use syntax::print::pprust; use syntax::ptr::P; use syntax::ThinVec; use syntax::token; @@ -16,7 +17,7 @@ use syntax::tokenstream::{TokenTree, TokenStream}; use syntax::source_map::{self, respan, Span}; use syntax::struct_span_err; use syntax_pos::BytePos; -use syntax_pos::symbol::{kw, sym}; +use syntax_pos::symbol::{kw, sym, Symbol}; use rustc_error_codes::*; @@ -1341,6 +1342,10 @@ impl<'a> Parser<'a> { let vlo = self.token.span; 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 struct_def = if self.check(&token::OpenDelim(token::Brace)) { @@ -1742,6 +1747,36 @@ impl<'a> Parser<'a> { ).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, attrs: Vec<Attribute>) -> P<Item> { P(Item { diff --git a/src/test/ui/enum/nested-enum.rs b/src/test/ui/enum/nested-enum.rs new file mode 100644 index 00000000000..80957b8a14c --- /dev/null +++ b/src/test/ui/enum/nested-enum.rs @@ -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() { } diff --git a/src/test/ui/enum/nested-enum.stderr b/src/test/ui/enum/nested-enum.stderr new file mode 100644 index 00000000000..7d6f57e88a8 --- /dev/null +++ b/src/test/ui/enum/nested-enum.stderr @@ -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 + |
