Skip to content

Commit 3fdc991

Browse files
tdittrfolkertdev
andcommitted
Improve error message for extern "C" unsafe fn()
This was handled correctly already for `extern unsafe fn()`. Co-authored-by: Folkert <[email protected]>
1 parent 33dd288 commit 3fdc991

File tree

5 files changed

+30
-14
lines changed

5 files changed

+30
-14
lines changed

compiler/rustc_parse/src/parser/item.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -2483,12 +2483,15 @@ impl<'a> Parser<'a> {
24832483
/// `check_pub` adds additional `pub` to the checks in case users place it
24842484
/// wrongly, can be used to ensure `pub` never comes after `default`.
24852485
pub(super) fn check_fn_front_matter(&mut self, check_pub: bool, case: Case) -> bool {
2486+
const ALL_QUALS: &[Symbol] =
2487+
&[kw::Pub, kw::Gen, kw::Const, kw::Async, kw::Unsafe, kw::Safe, kw::Extern];
2488+
24862489
// We use an over-approximation here.
24872490
// `const const`, `fn const` won't parse, but we're not stepping over other syntax either.
24882491
// `pub` is added in case users got confused with the ordering like `async pub fn`,
24892492
// only if it wasn't preceded by `default` as `default pub` is invalid.
24902493
let quals: &[Symbol] = if check_pub {
2491-
&[kw::Pub, kw::Gen, kw::Const, kw::Async, kw::Unsafe, kw::Safe, kw::Extern]
2494+
ALL_QUALS
24922495
} else {
24932496
&[kw::Gen, kw::Const, kw::Async, kw::Unsafe, kw::Safe, kw::Extern]
24942497
};
@@ -2518,9 +2521,9 @@ impl<'a> Parser<'a> {
25182521
|| self.check_keyword_case(kw::Extern, case)
25192522
&& self.look_ahead(1, |t| t.can_begin_string_literal())
25202523
&& (self.look_ahead(2, |t| t.is_keyword_case(kw::Fn, case)) ||
2521-
// this branch is only for better diagnostic in later, `pub` is not allowed here
2524+
// this branch is only for better diagnostics; `pub`, `unsafe`, etc. are not allowed here
25222525
(self.may_recover()
2523-
&& self.look_ahead(2, |t| t.is_keyword(kw::Pub))
2526+
&& self.look_ahead(2, |t| ALL_QUALS.iter().any(|&kw| t.is_keyword(kw)))
25242527
&& self.look_ahead(3, |t| t.is_keyword_case(kw::Fn, case))))
25252528
}
25262529

tests/ui/parser/issues/issue-19398.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
trait T {
22
extern "Rust" unsafe fn foo();
3-
//~^ ERROR expected `{`, found keyword `unsafe`
3+
//~^ ERROR expected `fn`, found keyword `unsafe`
4+
//~| NOTE expected `fn`
5+
//~| HELP `unsafe` must come before `extern "Rust"`
6+
//~| SUGGESTION unsafe extern "Rust"
7+
//~| NOTE keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`
48
}
59

610
fn main() {}
+7-7
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
error: expected `{`, found keyword `unsafe`
1+
error: expected `fn`, found keyword `unsafe`
22
--> $DIR/issue-19398.rs:2:19
33
|
4-
LL | trait T {
5-
| - while parsing this item list starting here
64
LL | extern "Rust" unsafe fn foo();
7-
| ^^^^^^ expected `{`
8-
LL |
9-
LL | }
10-
| - the item list ends here
5+
| --------------^^^^^^
6+
| | |
7+
| | expected `fn`
8+
| help: `unsafe` must come before `extern "Rust"`: `unsafe extern "Rust"`
9+
|
10+
= note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`
1111

1212
error: aborting due to 1 previous error
1313

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

+5-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
// Visibilities are tested elsewhere.
88

99
extern "C" unsafe fn test() {}
10-
//~^ ERROR
10+
//~^ ERROR expected `fn`, found keyword `unsafe`
11+
//~| NOTE expected `fn`
12+
//~| HELP `unsafe` must come before `extern "C"`
13+
//~| SUGGESTION unsafe extern "C"
14+
//~| NOTE keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`
1115

1216
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1-
error: expected `{`, found keyword `unsafe`
1+
error: expected `fn`, found keyword `unsafe`
22
--> $DIR/wrong-unsafe-abi.rs:9:12
33
|
44
LL | extern "C" unsafe fn test() {}
5-
| ^^^^^^ expected `{`
5+
| -----------^^^^^^
6+
| | |
7+
| | expected `fn`
8+
| help: `unsafe` must come before `extern "C"`: `unsafe extern "C"`
9+
|
10+
= note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`
611

712
error: aborting due to 1 previous error
813

0 commit comments

Comments
 (0)