From 3a13a721418b53ee6ca4c24fdbd17cc136ebcebb Mon Sep 17 00:00:00 2001 From: threadexception Date: Wed, 17 Nov 2021 16:31:56 +0100 Subject: [PATCH] Improve `unsafe` diagnostic --- compiler/rustc_parse/src/parser/item.rs | 28 +++++++++++++++++--- src/test/ui/parser/issues/issue-19398.stderr | 7 ++++- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 24a8df49ac7ee..6e9eaf0c0f947 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -933,10 +933,32 @@ impl<'a> Parser<'a> { attrs: &mut Vec, unsafety: Unsafe, ) -> PResult<'a, ItemInfo> { + let sp_start = self.prev_token.span; let abi = self.parse_abi(); // ABI? - let items = self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No))?; - let module = ast::ForeignMod { unsafety, abi, items }; - Ok((Ident::empty(), ItemKind::ForeignMod(module))) + 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) { + if err.message() == "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 `default`, `pub`, `const`, `async`, `unsafe`, `extern`"); + } + } + Err(err) + } + } } /// 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 1da00960adfe4..f9c3ca763f26e 100644 --- a/src/test/ui/parser/issues/issue-19398.stderr +++ b/src/test/ui/parser/issues/issue-19398.stderr @@ -4,10 +4,15 @@ error: expected `{`, found keyword `unsafe` LL | trait T { | - while parsing this item list starting here LL | extern "Rust" unsafe fn foo(); - | ^^^^^^ expected `{` + | --------------^^^^^^ + | | | + | | expected `{` + | help: `unsafe` must come before `extern "Rust"`: `unsafe extern "Rust"` LL | LL | } | - the item list ends here + | + = note: keyword order for functions declaration is `default`, `pub`, `const`, `async`, `unsafe`, `extern` error: aborting due to previous error