Recover on misspelled item keyword

This commit is contained in:
Sasha Pourcelot 2025-11-30 17:37:24 +00:00
parent f9b30df1b0
commit 9ffde14aa4
9 changed files with 111 additions and 59 deletions

View file

@ -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<Safety> {
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
}
}

View file

@ -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() {}

View file

@ -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;

View file

@ -4,20 +4,24 @@
trait Animal {
Type Result = u8;
//~^ ERROR expected one of
//~^ ERROR keyword `type` is written in the wrong case
}
Struct Foor {
//~^ ERROR expected one of
//~^ 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() {}

View file

@ -1,31 +1,74 @@
error: expected one of `!` or `::`, found `Result`
--> $DIR/recovery.rs:6:10
error: keyword `type` is written in the wrong case
--> $DIR/recovery.rs:6: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;
|
error: expected one of `!` or `::`, found `Foor`
--> $DIR/recovery.rs:10:8
error: keyword `struct` is written in the wrong case
--> $DIR/recovery.rs:10: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 {
|
error: aborting due to 2 previous errors
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

View file

@ -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() {}

View file

@ -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

View file

@ -1,4 +1,6 @@
Struct Foor {
//~^ ERROR expected one of
//~^ ERROR keyword `struct` is written in the wrong case
hello: String,
}
fn main() {}

View file

@ -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 {