Rollup merge of #117282 - clubby789:recover-wrong-function-header, r=TaKO8Ki

Recover from incorrectly ordered/duplicated function keywords

Fixes #115714
This commit is contained in:
Guillaume Gomez 2023-11-08 17:14:36 +01:00 committed by GitHub
commit c828371179
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 136 additions and 11 deletions

View File

@ -2401,22 +2401,39 @@ impl<'a> Parser<'a> {
Misplaced(Span), Misplaced(Span),
} }
// We may be able to recover
let mut recover_constness = constness;
let mut recover_asyncness = asyncness;
let mut recover_unsafety = unsafety;
// This will allow the machine fix to directly place the keyword in the correct place or to indicate // This will allow the machine fix to directly place the keyword in the correct place or to indicate
// that the keyword is already present and the second instance should be removed. // that the keyword is already present and the second instance should be removed.
let wrong_kw = if self.check_keyword(kw::Const) { let wrong_kw = if self.check_keyword(kw::Const) {
match constness { match constness {
Const::Yes(sp) => Some(WrongKw::Duplicated(sp)), Const::Yes(sp) => Some(WrongKw::Duplicated(sp)),
Const::No => Some(WrongKw::Misplaced(async_start_sp)), Const::No => {
recover_constness = Const::Yes(self.token.span);
Some(WrongKw::Misplaced(async_start_sp))
}
} }
} else if self.check_keyword(kw::Async) { } else if self.check_keyword(kw::Async) {
match asyncness { match asyncness {
Async::Yes { span, .. } => Some(WrongKw::Duplicated(span)), Async::Yes { span, .. } => Some(WrongKw::Duplicated(span)),
Async::No => Some(WrongKw::Misplaced(unsafe_start_sp)), Async::No => {
recover_asyncness = Async::Yes {
span: self.token.span,
closure_id: DUMMY_NODE_ID,
return_impl_trait_id: DUMMY_NODE_ID,
};
Some(WrongKw::Misplaced(unsafe_start_sp))
}
} }
} else if self.check_keyword(kw::Unsafe) { } else if self.check_keyword(kw::Unsafe) {
match unsafety { match unsafety {
Unsafe::Yes(sp) => Some(WrongKw::Duplicated(sp)), Unsafe::Yes(sp) => Some(WrongKw::Duplicated(sp)),
Unsafe::No => Some(WrongKw::Misplaced(ext_start_sp)), Unsafe::No => {
recover_unsafety = Unsafe::Yes(self.token.span);
Some(WrongKw::Misplaced(ext_start_sp))
}
} }
} else { } else {
None None
@ -2486,6 +2503,23 @@ impl<'a> Parser<'a> {
} }
} }
} }
if wrong_kw.is_some()
&& self.may_recover()
&& self.look_ahead(1, |tok| tok.is_keyword_case(kw::Fn, case))
{
// Advance past the misplaced keyword and `fn`
self.bump();
self.bump();
err.emit();
return Ok(FnHeader {
constness: recover_constness,
unsafety: recover_unsafety,
asyncness: recover_asyncness,
ext,
});
}
return Err(err); return Err(err);
} }
} }

View File

@ -3,3 +3,4 @@
pub async const fn x() {} pub async const fn x() {}
//~^ ERROR expected one of `extern`, `fn`, or `unsafe`, found keyword `const` //~^ ERROR expected one of `extern`, `fn`, or `unsafe`, found keyword `const`
//~| ERROR functions cannot be both `const` and `async`

View File

@ -9,5 +9,14 @@ LL | pub async const fn x() {}
| |
= note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` = note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`
error: aborting due to previous error error: functions cannot be both `const` and `async`
--> $DIR/no-async-const.rs:4:5
|
LL | pub async const fn x() {}
| ----^^^^^-^^^^^----------
| | |
| | `const` because of this
| `async` because of this
error: aborting due to 2 previous errors

View File

@ -9,3 +9,5 @@ impl S {
#[cfg(FALSE)] #[cfg(FALSE)]
unsafe async fn f() {} //~ ERROR expected one of `extern` or `fn`, found keyword `async` unsafe async fn f() {} //~ ERROR expected one of `extern` or `fn`, found keyword `async`
fn main() {}

View File

@ -1,16 +1,11 @@
error: expected one of `extern` or `fn`, found keyword `async` error: expected one of `extern` or `fn`, found keyword `async`
--> $DIR/no-unsafe-async.rs:7:12 --> $DIR/no-unsafe-async.rs:7:12
| |
LL | impl S {
| - while parsing this item list starting here
LL | #[cfg(FALSE)]
LL | unsafe async fn g() {} LL | unsafe async fn g() {}
| -------^^^^^ | -------^^^^^
| | | | | |
| | expected one of `extern` or `fn` | | expected one of `extern` or `fn`
| help: `async` must come before `unsafe`: `async unsafe` | help: `async` must come before `unsafe`: `async unsafe`
LL | }
| - the item list ends here
| |
= note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` = note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`

View File

@ -7,3 +7,8 @@ const async const fn test() {}
//~| NOTE expected one of `extern`, `fn`, or `unsafe` //~| NOTE expected one of `extern`, `fn`, or `unsafe`
//~| HELP `const` already used earlier, remove this one //~| HELP `const` already used earlier, remove this one
//~| NOTE `const` first seen here //~| NOTE `const` first seen here
//~| ERROR functions cannot be both `const` and `async`
//~| NOTE `const` because of this
//~| NOTE `async` because of this
fn main() {}

View File

@ -13,5 +13,14 @@ note: `const` first seen here
LL | const async const fn test() {} LL | const async const fn test() {}
| ^^^^^ | ^^^^^
error: aborting due to previous error error: functions cannot be both `const` and `async`
--> $DIR/const-async-const.rs:5:1
|
LL | const async const fn test() {}
| ^^^^^-^^^^^-------------------
| | |
| | `async` because of this
| `const` because of this
error: aborting due to 2 previous errors

View File

@ -0,0 +1,22 @@
// test for #115714
struct Misplaced;
impl Misplaced {
unsafe const fn from_u32(val: u32) {}
//~^ ERROR expected one of `extern` or `fn`
fn oof(self){}
}
struct Duplicated;
impl Duplicated {
unsafe unsafe fn from_u32(val: u32) {}
//~^ ERROR expected one of `extern` or `fn`
fn oof(self){}
}
fn main() {
Misplaced.oof();
Duplicated.oof();
}

View File

@ -0,0 +1,28 @@
error: expected one of `extern` or `fn`, found keyword `const`
--> $DIR/recovery.rs:6:12
|
LL | unsafe const fn from_u32(val: u32) {}
| -------^^^^^
| | |
| | expected one of `extern` or `fn`
| help: `const` must come before `unsafe`: `const unsafe`
|
= note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`
error: expected one of `extern` or `fn`, found keyword `unsafe`
--> $DIR/recovery.rs:14:12
|
LL | unsafe unsafe fn from_u32(val: u32) {}
| ^^^^^^
| |
| expected one of `extern` or `fn`
| help: `unsafe` already used earlier, remove this one
|
note: `unsafe` first seen here
--> $DIR/recovery.rs:14:5
|
LL | unsafe unsafe fn from_u32(val: u32) {}
| ^^^^^^
error: aborting due to 2 previous errors

View File

@ -12,3 +12,8 @@ async unsafe const fn test() {}
//~| HELP `const` must come before `async unsafe` //~| HELP `const` must come before `async unsafe`
//~| SUGGESTION const async unsafe //~| SUGGESTION const async unsafe
//~| NOTE keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` //~| NOTE keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`
//~| ERROR functions cannot be both `const` and `async`
//~| NOTE `const` because of this
//~| NOTE `async` because of this
fn main() {}

View File

@ -9,5 +9,14 @@ LL | async unsafe const fn test() {}
| |
= note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` = note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`
error: aborting due to previous error error: functions cannot be both `const` and `async`
--> $DIR/several-kw-jump.rs:9:1
|
LL | async unsafe const fn test() {}
| ^^^^^--------^^^^^-------------
| | |
| | `const` because of this
| `async` because of this
error: aborting due to 2 previous errors

View File

@ -12,3 +12,5 @@ unsafe async fn test() {}
//~| HELP `async` must come before `unsafe` //~| HELP `async` must come before `unsafe`
//~| SUGGESTION async unsafe //~| SUGGESTION async unsafe
//~| NOTE keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` //~| NOTE keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`
fn main() {}

View File

@ -12,3 +12,5 @@ unsafe const fn test() {}
//~| HELP `const` must come before `unsafe` //~| HELP `const` must come before `unsafe`
//~| SUGGESTION const unsafe //~| SUGGESTION const unsafe
//~| NOTE keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` //~| NOTE keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`
fn main() {}

View File

@ -12,3 +12,5 @@ extern unsafe fn test() {}
//~| HELP `unsafe` must come before `extern` //~| HELP `unsafe` must come before `extern`
//~| SUGGESTION unsafe extern //~| SUGGESTION unsafe extern
//~| NOTE keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` //~| NOTE keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`
fn main() {}