diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index e99347206fe50..6720399aacb07 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -996,35 +996,24 @@ impl<'a> Parser<'a> { fn parse_item_foreign_mod( &mut self, attrs: &mut Vec, - unsafety: Unsafe, + mut unsafety: Unsafe, ) -> PResult<'a, ItemInfo> { - let sp_start = self.prev_token.span; let abi = self.parse_abi(); // ABI? - match self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No)) { - Ok(items) => { - let module = ast::ForeignMod { unsafety, abi, items }; - 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) - } + if unsafety == Unsafe::No + && self.token.is_keyword(kw::Unsafe) + && 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))) } /// Parses a foreign item (one in an `extern { ... }` block). diff --git a/src/test/ui/parser/issues/issue-19398.stderr b/src/test/ui/parser/issues/issue-19398.stderr index bbd85374b4bcf..1da00960adfe4 100644 --- a/src/test/ui/parser/issues/issue-19398.stderr +++ b/src/test/ui/parser/issues/issue-19398.stderr @@ -4,15 +4,10 @@ error: expected `{`, found keyword `unsafe` LL | trait T { | - while parsing this item list starting here LL | extern "Rust" unsafe fn foo(); - | --------------^^^^^^ - | | | - | | expected `{` - | help: `unsafe` must come before `extern "Rust"`: `unsafe extern "Rust"` + | ^^^^^^ expected `{` LL | LL | } | - the item list ends here - | - = note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` error: aborting due to previous error diff --git a/src/test/ui/parser/unsafe-foreign-mod-2.rs b/src/test/ui/parser/unsafe-foreign-mod-2.rs new file mode 100644 index 0000000000000..77856fb67340e --- /dev/null +++ b/src/test/ui/parser/unsafe-foreign-mod-2.rs @@ -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() {} diff --git a/src/test/ui/parser/unsafe-foreign-mod-2.stderr b/src/test/ui/parser/unsafe-foreign-mod-2.stderr new file mode 100644 index 0000000000000..7cc2de141ae14 --- /dev/null +++ b/src/test/ui/parser/unsafe-foreign-mod-2.stderr @@ -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 +