Skip to content

Commit 3a13a72

Browse files
committed
Improve unsafe diagnostic
1 parent 84826fe commit 3a13a72

File tree

2 files changed

+31
-4
lines changed

2 files changed

+31
-4
lines changed

compiler/rustc_parse/src/parser/item.rs

+25-3
Original file line numberDiff line numberDiff line change
@@ -933,10 +933,32 @@ impl<'a> Parser<'a> {
933933
attrs: &mut Vec<Attribute>,
934934
unsafety: Unsafe,
935935
) -> PResult<'a, ItemInfo> {
936+
let sp_start = self.prev_token.span;
936937
let abi = self.parse_abi(); // ABI?
937-
let items = self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No))?;
938-
let module = ast::ForeignMod { unsafety, abi, items };
939-
Ok((Ident::empty(), ItemKind::ForeignMod(module)))
938+
match self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No)) {
939+
Ok(items) => {
940+
let module = ast::ForeignMod { unsafety, abi, items };
941+
Ok((Ident::empty(), ItemKind::ForeignMod(module)))
942+
}
943+
Err(mut err) => {
944+
let current_qual_sp = self.prev_token.span;
945+
let current_qual_sp = current_qual_sp.to(sp_start);
946+
if let Ok(current_qual) = self.span_to_snippet(current_qual_sp) {
947+
if err.message() == "expected `{`, found keyword `unsafe`" {
948+
let invalid_qual_sp = self.token.uninterpolated_span();
949+
let invalid_qual = self.span_to_snippet(invalid_qual_sp).unwrap();
950+
951+
err.span_suggestion(
952+
current_qual_sp.to(invalid_qual_sp),
953+
&format!("`{}` must come before `{}`", invalid_qual, current_qual),
954+
format!("{} {}", invalid_qual, current_qual),
955+
Applicability::MachineApplicable,
956+
).note("keyword order for functions declaration is `default`, `pub`, `const`, `async`, `unsafe`, `extern`");
957+
}
958+
}
959+
Err(err)
960+
}
961+
}
940962
}
941963

942964
/// Parses a foreign item (one in an `extern { ... }` block).

src/test/ui/parser/issues/issue-19398.stderr

+6-1
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,15 @@ error: expected `{`, found keyword `unsafe`
44
LL | trait T {
55
| - while parsing this item list starting here
66
LL | extern "Rust" unsafe fn foo();
7-
| ^^^^^^ expected `{`
7+
| --------------^^^^^^
8+
| | |
9+
| | expected `{`
10+
| help: `unsafe` must come before `extern "Rust"`: `unsafe extern "Rust"`
811
LL |
912
LL | }
1013
| - the item list ends here
14+
|
15+
= note: keyword order for functions declaration is `default`, `pub`, `const`, `async`, `unsafe`, `extern`
1116

1217
error: aborting due to previous error
1318

0 commit comments

Comments
 (0)