Skip to content

Commit c828371

Browse files
authoredNov 8, 2023
Rollup merge of #117282 - clubby789:recover-wrong-function-header, r=TaKO8Ki
Recover from incorrectly ordered/duplicated function keywords Fixes #115714
2 parents e05e4f3 + be0b42f commit c828371

14 files changed

+136
-11
lines changed
 

‎compiler/rustc_parse/src/parser/item.rs

+37-3
Original file line numberDiff line numberDiff line change
@@ -2401,22 +2401,39 @@ impl<'a> Parser<'a> {
24012401
Misplaced(Span),
24022402
}
24032403

2404+
// We may be able to recover
2405+
let mut recover_constness = constness;
2406+
let mut recover_asyncness = asyncness;
2407+
let mut recover_unsafety = unsafety;
24042408
// This will allow the machine fix to directly place the keyword in the correct place or to indicate
24052409
// that the keyword is already present and the second instance should be removed.
24062410
let wrong_kw = if self.check_keyword(kw::Const) {
24072411
match constness {
24082412
Const::Yes(sp) => Some(WrongKw::Duplicated(sp)),
2409-
Const::No => Some(WrongKw::Misplaced(async_start_sp)),
2413+
Const::No => {
2414+
recover_constness = Const::Yes(self.token.span);
2415+
Some(WrongKw::Misplaced(async_start_sp))
2416+
}
24102417
}
24112418
} else if self.check_keyword(kw::Async) {
24122419
match asyncness {
24132420
Async::Yes { span, .. } => Some(WrongKw::Duplicated(span)),
2414-
Async::No => Some(WrongKw::Misplaced(unsafe_start_sp)),
2421+
Async::No => {
2422+
recover_asyncness = Async::Yes {
2423+
span: self.token.span,
2424+
closure_id: DUMMY_NODE_ID,
2425+
return_impl_trait_id: DUMMY_NODE_ID,
2426+
};
2427+
Some(WrongKw::Misplaced(unsafe_start_sp))
2428+
}
24152429
}
24162430
} else if self.check_keyword(kw::Unsafe) {
24172431
match unsafety {
24182432
Unsafe::Yes(sp) => Some(WrongKw::Duplicated(sp)),
2419-
Unsafe::No => Some(WrongKw::Misplaced(ext_start_sp)),
2433+
Unsafe::No => {
2434+
recover_unsafety = Unsafe::Yes(self.token.span);
2435+
Some(WrongKw::Misplaced(ext_start_sp))
2436+
}
24202437
}
24212438
} else {
24222439
None
@@ -2486,6 +2503,23 @@ impl<'a> Parser<'a> {
24862503
}
24872504
}
24882505
}
2506+
2507+
if wrong_kw.is_some()
2508+
&& self.may_recover()
2509+
&& self.look_ahead(1, |tok| tok.is_keyword_case(kw::Fn, case))
2510+
{
2511+
// Advance past the misplaced keyword and `fn`
2512+
self.bump();
2513+
self.bump();
2514+
err.emit();
2515+
return Ok(FnHeader {
2516+
constness: recover_constness,
2517+
unsafety: recover_unsafety,
2518+
asyncness: recover_asyncness,
2519+
ext,
2520+
});
2521+
}
2522+
24892523
return Err(err);
24902524
}
24912525
}

‎tests/ui/async-await/no-async-const.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33

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

‎tests/ui/async-await/no-async-const.stderr

+10-1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,14 @@ LL | pub async const fn x() {}
99
|
1010
= note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`
1111

12-
error: aborting due to previous error
12+
error: functions cannot be both `const` and `async`
13+
--> $DIR/no-async-const.rs:4:5
14+
|
15+
LL | pub async const fn x() {}
16+
| ----^^^^^-^^^^^----------
17+
| | |
18+
| | `const` because of this
19+
| `async` because of this
20+
21+
error: aborting due to 2 previous errors
1322

‎tests/ui/async-await/no-unsafe-async.rs

+2
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,5 @@ impl S {
99

1010
#[cfg(FALSE)]
1111
unsafe async fn f() {} //~ ERROR expected one of `extern` or `fn`, found keyword `async`
12+
13+
fn main() {}

‎tests/ui/async-await/no-unsafe-async.stderr

-5
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,11 @@
11
error: expected one of `extern` or `fn`, found keyword `async`
22
--> $DIR/no-unsafe-async.rs:7:12
33
|
4-
LL | impl S {
5-
| - while parsing this item list starting here
6-
LL | #[cfg(FALSE)]
74
LL | unsafe async fn g() {}
85
| -------^^^^^
96
| | |
107
| | expected one of `extern` or `fn`
118
| help: `async` must come before `unsafe`: `async unsafe`
12-
LL | }
13-
| - the item list ends here
149
|
1510
= note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`
1611

‎tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs

+5
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,8 @@ const async const fn test() {}
77
//~| NOTE expected one of `extern`, `fn`, or `unsafe`
88
//~| HELP `const` already used earlier, remove this one
99
//~| NOTE `const` first seen here
10+
//~| ERROR functions cannot be both `const` and `async`
11+
//~| NOTE `const` because of this
12+
//~| NOTE `async` because of this
13+
14+
fn main() {}

‎tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.stderr

+10-1
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,14 @@ note: `const` first seen here
1313
LL | const async const fn test() {}
1414
| ^^^^^
1515

16-
error: aborting due to previous error
16+
error: functions cannot be both `const` and `async`
17+
--> $DIR/const-async-const.rs:5:1
18+
|
19+
LL | const async const fn test() {}
20+
| ^^^^^-^^^^^-------------------
21+
| | |
22+
| | `async` because of this
23+
| `const` because of this
24+
25+
error: aborting due to 2 previous errors
1726

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// test for #115714
2+
3+
struct Misplaced;
4+
5+
impl Misplaced {
6+
unsafe const fn from_u32(val: u32) {}
7+
//~^ ERROR expected one of `extern` or `fn`
8+
fn oof(self){}
9+
}
10+
11+
struct Duplicated;
12+
13+
impl Duplicated {
14+
unsafe unsafe fn from_u32(val: u32) {}
15+
//~^ ERROR expected one of `extern` or `fn`
16+
fn oof(self){}
17+
}
18+
19+
fn main() {
20+
Misplaced.oof();
21+
Duplicated.oof();
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
error: expected one of `extern` or `fn`, found keyword `const`
2+
--> $DIR/recovery.rs:6:12
3+
|
4+
LL | unsafe const fn from_u32(val: u32) {}
5+
| -------^^^^^
6+
| | |
7+
| | expected one of `extern` or `fn`
8+
| help: `const` must come before `unsafe`: `const unsafe`
9+
|
10+
= note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`
11+
12+
error: expected one of `extern` or `fn`, found keyword `unsafe`
13+
--> $DIR/recovery.rs:14:12
14+
|
15+
LL | unsafe unsafe fn from_u32(val: u32) {}
16+
| ^^^^^^
17+
| |
18+
| expected one of `extern` or `fn`
19+
| help: `unsafe` already used earlier, remove this one
20+
|
21+
note: `unsafe` first seen here
22+
--> $DIR/recovery.rs:14:5
23+
|
24+
LL | unsafe unsafe fn from_u32(val: u32) {}
25+
| ^^^^^^
26+
27+
error: aborting due to 2 previous errors
28+

‎tests/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.rs

+5
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,8 @@ async unsafe const fn test() {}
1212
//~| HELP `const` must come before `async unsafe`
1313
//~| SUGGESTION const async unsafe
1414
//~| NOTE keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`
15+
//~| ERROR functions cannot be both `const` and `async`
16+
//~| NOTE `const` because of this
17+
//~| NOTE `async` because of this
18+
19+
fn main() {}

‎tests/ui/parser/issues/issue-87217-keyword-order/several-kw-jump.stderr

+10-1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,14 @@ LL | async unsafe const fn test() {}
99
|
1010
= note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`
1111

12-
error: aborting due to previous error
12+
error: functions cannot be both `const` and `async`
13+
--> $DIR/several-kw-jump.rs:9:1
14+
|
15+
LL | async unsafe const fn test() {}
16+
| ^^^^^--------^^^^^-------------
17+
| | |
18+
| | `const` because of this
19+
| `async` because of this
20+
21+
error: aborting due to 2 previous errors
1322

‎tests/ui/parser/issues/issue-87217-keyword-order/wrong-async.rs

+2
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,5 @@ unsafe async fn test() {}
1212
//~| HELP `async` must come before `unsafe`
1313
//~| SUGGESTION async unsafe
1414
//~| NOTE keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`
15+
16+
fn main() {}

‎tests/ui/parser/issues/issue-87217-keyword-order/wrong-const.rs

+2
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,5 @@ unsafe const fn test() {}
1212
//~| HELP `const` must come before `unsafe`
1313
//~| SUGGESTION const unsafe
1414
//~| NOTE keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`
15+
16+
fn main() {}

‎tests/ui/parser/issues/issue-87217-keyword-order/wrong-unsafe.rs

+2
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,5 @@ extern unsafe fn test() {}
1212
//~| HELP `unsafe` must come before `extern`
1313
//~| SUGGESTION unsafe extern
1414
//~| NOTE keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`
15+
16+
fn main() {}

0 commit comments

Comments
 (0)
Please sign in to comment.