diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 86991f047e46d..abc0ffa87d3d0 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -228,8 +228,8 @@ impl<'a> Parser<'a> { body, define_opaque: None, })) - } else if self.eat_keyword(exp!(Extern)) { - if self.eat_keyword(exp!(Crate)) { + } else if self.eat_keyword_case(exp!(Extern), case) { + if self.eat_keyword_case(exp!(Crate), case) { // EXTERN CRATE self.parse_item_extern_crate()? } else { @@ -241,19 +241,17 @@ impl<'a> Parser<'a> { let safety = self.parse_safety(Case::Sensitive); self.expect_keyword(exp!(Extern))?; self.parse_item_foreign_mod(attrs, safety)? - } else if self.is_static_global() { - let safety = self.parse_safety(Case::Sensitive); + } else if let Some(safety) = self.parse_global_static_front_matter(case) { // STATIC ITEM - self.bump(); // `static` let mutability = self.parse_mutability(); self.parse_static_item(safety, mutability)? - } else if self.check_keyword(exp!(Trait)) || self.check_trait_front_matter() { + } else if self.check_keyword_case(exp!(Trait), case) || self.check_trait_front_matter() { // TRAIT ITEM self.parse_item_trait(attrs, lo)? } else if self.check_impl_frontmatter() { // IMPL ITEM self.parse_item_impl(attrs, def_())? - } else if let Const::Yes(const_span) = self.parse_constness(Case::Sensitive) { + } else if let Const::Yes(const_span) = self.parse_constness(case) { // CONST ITEM self.recover_const_mut(const_span); self.recover_missing_kw_before_item()?; @@ -268,18 +266,18 @@ impl<'a> Parser<'a> { })) } else if self.is_reuse_path_item() { self.parse_item_delegation()? - } else if self.check_keyword(exp!(Mod)) - || self.check_keyword(exp!(Unsafe)) && self.is_keyword_ahead(1, &[kw::Mod]) + } else if self.check_keyword_case(exp!(Mod), case) + || self.check_keyword_case(exp!(Unsafe), case) && self.is_keyword_ahead(1, &[kw::Mod]) { // MODULE ITEM self.parse_item_mod(attrs)? - } else if self.eat_keyword(exp!(Type)) { + } else if self.eat_keyword_case(exp!(Type), case) { // TYPE ITEM self.parse_type_alias(def_())? - } else if self.eat_keyword(exp!(Enum)) { + } else if self.eat_keyword_case(exp!(Enum), case) { // ENUM ITEM self.parse_item_enum()? - } else if self.eat_keyword(exp!(Struct)) { + } else if self.eat_keyword_case(exp!(Struct), case) { // STRUCT ITEM self.parse_item_struct()? } else if self.is_kw_followed_by_ident(kw::Union) { @@ -289,7 +287,7 @@ impl<'a> Parser<'a> { } else if self.is_builtin() { // BUILTIN# ITEM return self.parse_item_builtin(); - } else if self.eat_keyword(exp!(Macro)) { + } else if self.eat_keyword_case(exp!(Macro), case) { // MACROS 2.0 ITEM self.parse_item_decl_macro(lo)? } else if let IsMacroRulesItem::Yes { has_bang } = self.is_macro_rules_item() { @@ -1324,19 +1322,28 @@ impl<'a> Parser<'a> { == Some(true) } - fn is_static_global(&mut self) -> bool { - if self.check_keyword(exp!(Static)) { + fn parse_global_static_front_matter(&mut self, case: Case) -> Option { + let is_global_static = if self.check_keyword_case(exp!(Static), case) { // Check if this could be a closure. !self.look_ahead(1, |token| { - if token.is_keyword(kw::Move) || token.is_keyword(kw::Use) { + if token.is_keyword_case(kw::Move, case) || token.is_keyword_case(kw::Use, case) { return true; } matches!(token.kind, token::Or | token::OrOr) }) } else { // `$qual static` - (self.check_keyword(exp!(Unsafe)) || self.check_keyword(exp!(Safe))) - && self.look_ahead(1, |t| t.is_keyword(kw::Static)) + (self.check_keyword_case(exp!(Unsafe), case) + || self.check_keyword_case(exp!(Safe), case)) + && self.look_ahead(1, |t| t.is_keyword_case(kw::Static, case)) + }; + + if is_global_static { + let safety = self.parse_safety(case); + let _ = self.eat_keyword_case(exp!(Static), case); + Some(safety) + } else { + None } } diff --git a/tests/ui/parser/misspelled-keywords/assoc-type.rs b/tests/ui/parser/misspelled-keywords/assoc-type.rs index a6b694a2abe6b..31328d010ae91 100644 --- a/tests/ui/parser/misspelled-keywords/assoc-type.rs +++ b/tests/ui/parser/misspelled-keywords/assoc-type.rs @@ -1,6 +1,8 @@ +#![feature(associated_type_defaults)] + trait Animal { Type Result = u8; - //~^ ERROR expected one of + //~^ ERROR keyword `type` is written in the wrong case } fn main() {} diff --git a/tests/ui/parser/misspelled-keywords/assoc-type.stderr b/tests/ui/parser/misspelled-keywords/assoc-type.stderr index e529b477c05bc..4a777a558c727 100644 --- a/tests/ui/parser/misspelled-keywords/assoc-type.stderr +++ b/tests/ui/parser/misspelled-keywords/assoc-type.stderr @@ -1,15 +1,10 @@ -error: expected one of `!` or `::`, found `Result` - --> $DIR/assoc-type.rs:2:10 +error: keyword `type` is written in the wrong case + --> $DIR/assoc-type.rs:4:5 | -LL | trait Animal { - | - while parsing this item list starting here LL | Type Result = u8; - | ^^^^^^ expected one of `!` or `::` -LL | -LL | } - | - the item list ends here + | ^^^^ | -help: write keyword `type` in lowercase +help: write it in lowercase | LL - Type Result = u8; LL + type Result = u8; diff --git a/tests/ui/parser/misspelled-keywords/recovery.rs b/tests/ui/parser/misspelled-keywords/recovery.rs new file mode 100644 index 0000000000000..f56709c0ce97f --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/recovery.rs @@ -0,0 +1,27 @@ +// Shows that we perform recovery on misspelled item keyword. + +#![feature(associated_type_defaults)] + +trait Animal { + Type Result = u8; + //~^ ERROR keyword `type` is written in the wrong case +} + +Struct Foor { + //~^ ERROR keyword `struct` is written in the wrong case + hello: String, +} + +Const A: u8 = 10; +//~^ ERROR keyword `const` is written in the wrong case + +Fn code() {} +//~^ ERROR keyword `fn` is written in the wrong case + +Static a: u8 = 0; +//~^ ERROR keyword `static` is written in the wrong case + +usee a::b; +//~^ ERROR expected one of + +fn main() {} diff --git a/tests/ui/parser/misspelled-keywords/recovery.stderr b/tests/ui/parser/misspelled-keywords/recovery.stderr new file mode 100644 index 0000000000000..6c2e8261e9719 --- /dev/null +++ b/tests/ui/parser/misspelled-keywords/recovery.stderr @@ -0,0 +1,74 @@ +error: keyword `type` is written in the wrong case + --> $DIR/recovery.rs:6:5 + | +LL | Type Result = u8; + | ^^^^ + | +help: write it in lowercase + | +LL - Type Result = u8; +LL + type Result = u8; + | + +error: keyword `struct` is written in the wrong case + --> $DIR/recovery.rs:10:1 + | +LL | Struct Foor { + | ^^^^^^ + | +help: write it in lowercase (notice the capitalization) + | +LL - Struct Foor { +LL + struct Foor { + | + +error: keyword `const` is written in the wrong case + --> $DIR/recovery.rs:15:1 + | +LL | Const A: u8 = 10; + | ^^^^^ + | +help: write it in lowercase (notice the capitalization) + | +LL - Const A: u8 = 10; +LL + const A: u8 = 10; + | + +error: keyword `fn` is written in the wrong case + --> $DIR/recovery.rs:18:1 + | +LL | Fn code() {} + | ^^ + | +help: write it in lowercase (notice the capitalization) + | +LL - Fn code() {} +LL + fn code() {} + | + +error: keyword `static` is written in the wrong case + --> $DIR/recovery.rs:21:1 + | +LL | Static a: u8 = 0; + | ^^^^^^ + | +help: write it in lowercase (notice the capitalization) + | +LL - Static a: u8 = 0; +LL + static a: u8 = 0; + | + +error: expected one of `!` or `::`, found `a` + --> $DIR/recovery.rs:24:6 + | +LL | usee a::b; + | ^ expected one of `!` or `::` + | +help: there is a keyword `use` with a similar name + | +LL - usee a::b; +LL + use a::b; + | + +error: aborting due to 6 previous errors + diff --git a/tests/ui/parser/misspelled-keywords/static.rs b/tests/ui/parser/misspelled-keywords/static.rs index 240f4f52c8dc8..29dd21b6b56c7 100644 --- a/tests/ui/parser/misspelled-keywords/static.rs +++ b/tests/ui/parser/misspelled-keywords/static.rs @@ -1,4 +1,3 @@ -Static a = 0; -//~^ ERROR expected one of - +Static a: u32 = 0; +//~^ ERROR keyword `static` is written in the wrong case fn main() {} diff --git a/tests/ui/parser/misspelled-keywords/static.stderr b/tests/ui/parser/misspelled-keywords/static.stderr index 0df40bcdc33b5..75c34f4839505 100644 --- a/tests/ui/parser/misspelled-keywords/static.stderr +++ b/tests/ui/parser/misspelled-keywords/static.stderr @@ -1,13 +1,13 @@ -error: expected one of `!` or `::`, found `a` - --> $DIR/static.rs:1:8 +error: keyword `static` is written in the wrong case + --> $DIR/static.rs:1:1 | -LL | Static a = 0; - | ^ expected one of `!` or `::` +LL | Static a: u32 = 0; + | ^^^^^^ | -help: write keyword `static` in lowercase (notice the capitalization) +help: write it in lowercase (notice the capitalization) | -LL - Static a = 0; -LL + static a = 0; +LL - Static a: u32 = 0; +LL + static a: u32 = 0; | error: aborting due to 1 previous error diff --git a/tests/ui/parser/misspelled-keywords/struct.rs b/tests/ui/parser/misspelled-keywords/struct.rs index 0f64dec6f56b3..5c76ce7622f95 100644 --- a/tests/ui/parser/misspelled-keywords/struct.rs +++ b/tests/ui/parser/misspelled-keywords/struct.rs @@ -1,4 +1,6 @@ Struct Foor { -//~^ ERROR expected one of + //~^ ERROR keyword `struct` is written in the wrong case hello: String, } + +fn main() {} diff --git a/tests/ui/parser/misspelled-keywords/struct.stderr b/tests/ui/parser/misspelled-keywords/struct.stderr index af8614ef14b71..a6709111d4ae7 100644 --- a/tests/ui/parser/misspelled-keywords/struct.stderr +++ b/tests/ui/parser/misspelled-keywords/struct.stderr @@ -1,10 +1,10 @@ -error: expected one of `!` or `::`, found `Foor` - --> $DIR/struct.rs:1:8 +error: keyword `struct` is written in the wrong case + --> $DIR/struct.rs:1:1 | LL | Struct Foor { - | ^^^^ expected one of `!` or `::` + | ^^^^^^ | -help: write keyword `struct` in lowercase (notice the capitalization) +help: write it in lowercase (notice the capitalization) | LL - Struct Foor { LL + struct Foor {