Rollup merge of #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.
This commit is contained in:
commit
22da719762
4 changed files with 52 additions and 32 deletions
|
@ -996,36 +996,25 @@ impl<'a> Parser<'a> {
|
||||||
fn parse_item_foreign_mod(
|
fn parse_item_foreign_mod(
|
||||||
&mut self,
|
&mut self,
|
||||||
attrs: &mut Vec<Attribute>,
|
attrs: &mut Vec<Attribute>,
|
||||||
unsafety: Unsafe,
|
mut unsafety: Unsafe,
|
||||||
) -> PResult<'a, ItemInfo> {
|
) -> PResult<'a, ItemInfo> {
|
||||||
let sp_start = self.prev_token.span;
|
|
||||||
let abi = self.parse_abi(); // ABI?
|
let abi = self.parse_abi(); // ABI?
|
||||||
match self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No)) {
|
if unsafety == Unsafe::No
|
||||||
Ok(items) => {
|
&& self.token.is_keyword(kw::Unsafe)
|
||||||
let module = ast::ForeignMod { unsafety, abi, items };
|
&& self.look_ahead(1, |t| t.kind == token::OpenDelim(Delimiter::Brace))
|
||||||
|
{
|
||||||
|
let mut err = self.expect(&token::OpenDelim(Delimiter::Brace)).unwrap_err();
|
||||||
|
err.emit();
|
||||||
|
unsafety = Unsafe::Yes(self.token.span);
|
||||||
|
self.eat_keyword(kw::Unsafe);
|
||||||
|
}
|
||||||
|
let module = ast::ForeignMod {
|
||||||
|
unsafety,
|
||||||
|
abi,
|
||||||
|
items: self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No))?,
|
||||||
|
};
|
||||||
Ok((Ident::empty(), ItemKind::ForeignMod(module)))
|
Ok((Ident::empty(), ItemKind::ForeignMod(module)))
|
||||||
}
|
}
|
||||||
Err(mut err) => {
|
|
||||||
let current_qual_sp = self.prev_token.span;
|
|
||||||
let current_qual_sp = current_qual_sp.to(sp_start);
|
|
||||||
if let Ok(current_qual) = self.span_to_snippet(current_qual_sp) {
|
|
||||||
// FIXME(davidtwco): avoid depending on the error message text
|
|
||||||
if err.message[0].0.expect_str() == "expected `{`, found keyword `unsafe`" {
|
|
||||||
let invalid_qual_sp = self.token.uninterpolated_span();
|
|
||||||
let invalid_qual = self.span_to_snippet(invalid_qual_sp).unwrap();
|
|
||||||
|
|
||||||
err.span_suggestion(
|
|
||||||
current_qual_sp.to(invalid_qual_sp),
|
|
||||||
&format!("`{}` must come before `{}`", invalid_qual, current_qual),
|
|
||||||
format!("{} {}", invalid_qual, current_qual),
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
).note("keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parses a foreign item (one in an `extern { ... }` block).
|
/// Parses a foreign item (one in an `extern { ... }` block).
|
||||||
pub fn parse_foreign_item(
|
pub fn parse_foreign_item(
|
||||||
|
|
|
@ -4,15 +4,10 @@ error: expected `{`, found keyword `unsafe`
|
||||||
LL | trait T {
|
LL | trait T {
|
||||||
| - while parsing this item list starting here
|
| - while parsing this item list starting here
|
||||||
LL | extern "Rust" unsafe fn foo();
|
LL | extern "Rust" unsafe fn foo();
|
||||||
| --------------^^^^^^
|
| ^^^^^^ expected `{`
|
||||||
| | |
|
|
||||||
| | expected `{`
|
|
||||||
| help: `unsafe` must come before `extern "Rust"`: `unsafe extern "Rust"`
|
|
||||||
LL |
|
LL |
|
||||||
LL | }
|
LL | }
|
||||||
| - the item list ends here
|
| - the item list ends here
|
||||||
|
|
|
||||||
= note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern`
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
8
src/test/ui/parser/unsafe-foreign-mod-2.rs
Normal file
8
src/test/ui/parser/unsafe-foreign-mod-2.rs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
extern "C" unsafe {
|
||||||
|
//~^ ERROR expected `{`, found keyword `unsafe`
|
||||||
|
//~| ERROR extern block cannot be declared unsafe
|
||||||
|
unsafe fn foo();
|
||||||
|
//~^ ERROR functions in `extern` blocks cannot have qualifiers
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
28
src/test/ui/parser/unsafe-foreign-mod-2.stderr
Normal file
28
src/test/ui/parser/unsafe-foreign-mod-2.stderr
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
error: expected `{`, found keyword `unsafe`
|
||||||
|
--> $DIR/unsafe-foreign-mod-2.rs:1:12
|
||||||
|
|
|
||||||
|
LL | extern "C" unsafe {
|
||||||
|
| ^^^^^^ expected `{`
|
||||||
|
|
||||||
|
error: extern block cannot be declared unsafe
|
||||||
|
--> $DIR/unsafe-foreign-mod-2.rs:1:12
|
||||||
|
|
|
||||||
|
LL | extern "C" unsafe {
|
||||||
|
| ^^^^^^
|
||||||
|
|
||||||
|
error: functions in `extern` blocks cannot have qualifiers
|
||||||
|
--> $DIR/unsafe-foreign-mod-2.rs:4:15
|
||||||
|
|
|
||||||
|
LL | extern "C" unsafe {
|
||||||
|
| ----------------- in this `extern` block
|
||||||
|
...
|
||||||
|
LL | unsafe fn foo();
|
||||||
|
| ^^^
|
||||||
|
|
|
||||||
|
help: remove the qualifiers
|
||||||
|
|
|
||||||
|
LL | fn foo();
|
||||||
|
| ~~
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue