Skip to content

Commit 0cf8c57

Browse files
Rollup merge of rust-lang#97172 - SparrowLii:unsafe_extern, r=compiler-errors
Optimize the diagnostic generation for `extern unsafe` This PR does the following about diagnostic generation when parsing foreign mod: 1. Fixes the FIXME about avoiding depending on the error message text. 2. Continue parsing when `unsafe` is followed by `{` (just like `unsafe extern {...}`). 3. Add test case.
2 parents bac701a + 0be2ca9 commit 0cf8c57

File tree

4 files changed

+52
-32
lines changed

4 files changed

+52
-32
lines changed

compiler/rustc_parse/src/parser/item.rs

+15-26
Original file line numberDiff line numberDiff line change
@@ -996,35 +996,24 @@ impl<'a> Parser<'a> {
996996
fn parse_item_foreign_mod(
997997
&mut self,
998998
attrs: &mut Vec<Attribute>,
999-
unsafety: Unsafe,
999+
mut unsafety: Unsafe,
10001000
) -> PResult<'a, ItemInfo> {
1001-
let sp_start = self.prev_token.span;
10021001
let abi = self.parse_abi(); // ABI?
1003-
match self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No)) {
1004-
Ok(items) => {
1005-
let module = ast::ForeignMod { unsafety, abi, items };
1006-
Ok((Ident::empty(), ItemKind::ForeignMod(module)))
1007-
}
1008-
Err(mut err) => {
1009-
let current_qual_sp = self.prev_token.span;
1010-
let current_qual_sp = current_qual_sp.to(sp_start);
1011-
if let Ok(current_qual) = self.span_to_snippet(current_qual_sp) {
1012-
// FIXME(davidtwco): avoid depending on the error message text
1013-
if err.message[0].0.expect_str() == "expected `{`, found keyword `unsafe`" {
1014-
let invalid_qual_sp = self.token.uninterpolated_span();
1015-
let invalid_qual = self.span_to_snippet(invalid_qual_sp).unwrap();
1016-
1017-
err.span_suggestion(
1018-
current_qual_sp.to(invalid_qual_sp),
1019-
&format!("`{}` must come before `{}`", invalid_qual, current_qual),
1020-
format!("{} {}", invalid_qual, current_qual),
1021-
Applicability::MachineApplicable,
1022-
).note("keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`");
1023-
}
1024-
}
1025-
Err(err)
1026-
}
1002+
if unsafety == Unsafe::No
1003+
&& self.token.is_keyword(kw::Unsafe)
1004+
&& self.look_ahead(1, |t| t.kind == token::OpenDelim(Delimiter::Brace))
1005+
{
1006+
let mut err = self.expect(&token::OpenDelim(Delimiter::Brace)).unwrap_err();
1007+
err.emit();
1008+
unsafety = Unsafe::Yes(self.token.span);
1009+
self.eat_keyword(kw::Unsafe);
10271010
}
1011+
let module = ast::ForeignMod {
1012+
unsafety,
1013+
abi,
1014+
items: self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No))?,
1015+
};
1016+
Ok((Ident::empty(), ItemKind::ForeignMod(module)))
10281017
}
10291018

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

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

+1-6
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,10 @@ 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-
| --------------^^^^^^
8-
| | |
9-
| | expected `{`
10-
| help: `unsafe` must come before `extern "Rust"`: `unsafe extern "Rust"`
7+
| ^^^^^^ expected `{`
118
LL |
129
LL | }
1310
| - the item list ends here
14-
|
15-
= note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`
1611

1712
error: aborting due to previous error
1813

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
extern "C" unsafe {
2+
//~^ ERROR expected `{`, found keyword `unsafe`
3+
//~| ERROR extern block cannot be declared unsafe
4+
unsafe fn foo();
5+
//~^ ERROR functions in `extern` blocks cannot have qualifiers
6+
}
7+
8+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
error: expected `{`, found keyword `unsafe`
2+
--> $DIR/unsafe-foreign-mod-2.rs:1:12
3+
|
4+
LL | extern "C" unsafe {
5+
| ^^^^^^ expected `{`
6+
7+
error: extern block cannot be declared unsafe
8+
--> $DIR/unsafe-foreign-mod-2.rs:1:12
9+
|
10+
LL | extern "C" unsafe {
11+
| ^^^^^^
12+
13+
error: functions in `extern` blocks cannot have qualifiers
14+
--> $DIR/unsafe-foreign-mod-2.rs:4:15
15+
|
16+
LL | extern "C" unsafe {
17+
| ----------------- in this `extern` block
18+
...
19+
LL | unsafe fn foo();
20+
| ^^^
21+
|
22+
help: remove the qualifiers
23+
|
24+
LL | fn foo();
25+
| ~~
26+
27+
error: aborting due to 3 previous errors
28+

0 commit comments

Comments
 (0)