From cb26fa07bbb3e7c200c5511b3d010c4208a19a18 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 30 Oct 2024 13:12:08 +0100 Subject: [PATCH 1/2] Improve the missing_abi lint. --- compiler/rustc_ast/src/ast.rs | 2 ++ compiler/rustc_ast/src/mut_visit.rs | 2 +- compiler/rustc_ast/src/visit.rs | 2 +- compiler/rustc_ast_passes/src/ast_validation.rs | 13 ++++++------- compiler/rustc_lint/messages.ftl | 2 +- compiler/rustc_lint/src/lints.rs | 4 +--- compiler/rustc_parse/src/parser/item.rs | 2 ++ 7 files changed, 14 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 8e4f4c8e71a2e..ec6ca70ae0a4b 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2810,6 +2810,8 @@ pub struct ModSpans { /// E.g., `extern { .. }` or `extern "C" { .. }`. #[derive(Clone, Encodable, Decodable, Debug)] pub struct ForeignMod { + /// Span of the `extern` keyword. + pub extern_span: Span, /// `unsafe` keyword accepted syntactically for macro DSLs, but not /// semantically by Rust. pub safety: Safety, diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 2afbd979c3023..44bb44cb7288e 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -525,7 +525,7 @@ pub fn walk_ty(vis: &mut T, ty: &mut P) { } fn walk_foreign_mod(vis: &mut T, foreign_mod: &mut ForeignMod) { - let ForeignMod { safety, abi: _, items } = foreign_mod; + let ForeignMod { extern_span: _, safety, abi: _, items } = foreign_mod; visit_safety(vis, safety); items.flat_map_in_place(|item| vis.flat_map_foreign_item(item)); } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index eb71ec5f4ec93..2f8115441de9e 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -366,7 +366,7 @@ impl WalkItemKind for ItemKind { } ModKind::Unloaded => {} }, - ItemKind::ForeignMod(ForeignMod { safety: _, abi: _, items }) => { + ItemKind::ForeignMod(ForeignMod { extern_span: _, safety: _, abi: _, items }) => { walk_list!(visitor, visit_foreign_item, items); } ItemKind::GlobalAsm(asm) => try_visit!(visitor.visit_inline_asm(asm)), diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 0a4f86d4822f7..dee48586f34cf 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -677,9 +677,8 @@ impl<'a> AstValidator<'a> { Self::check_decl_no_pat(&bfty.decl, |span, _, _| { self.dcx().emit_err(errors::PatternFnPointer { span }); }); - if let Extern::Implicit(_) = bfty.ext { - let sig_span = self.sess.source_map().next_point(ty.span.shrink_to_lo()); - self.maybe_lint_missing_abi(sig_span, ty.id); + if let Extern::Implicit(extern_span) = bfty.ext { + self.maybe_lint_missing_abi(extern_span, ty.id); } } TyKind::TraitObject(bounds, ..) => { @@ -953,7 +952,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { walk_list!(self, visit_attribute, &item.attrs); return; // Avoid visiting again. } - ItemKind::ForeignMod(ForeignMod { abi, safety, .. }) => { + ItemKind::ForeignMod(ForeignMod { extern_span, abi, safety, .. }) => { self.with_in_extern_mod(*safety, |this| { let old_item = mem::replace(&mut this.extern_mod, Some(item.span)); this.visibility_not_permitted( @@ -977,7 +976,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } if abi.is_none() { - this.maybe_lint_missing_abi(item.span, item.id); + this.maybe_lint_missing_abi(*extern_span, item.id); } visit::walk_item(this, item); this.extern_mod = old_item; @@ -1350,13 +1349,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if let FnKind::Fn( _, _, - FnSig { span: sig_span, header: FnHeader { ext: Extern::Implicit(_), .. }, .. }, + FnSig { header: FnHeader { ext: Extern::Implicit(extern_span), .. }, .. }, _, _, _, ) = fk { - self.maybe_lint_missing_abi(*sig_span, id); + self.maybe_lint_missing_abi(*extern_span, id); } // Functions without bodies cannot have patterns. diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 3fa43296dfcac..9187f6caad43c 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -268,7 +268,7 @@ lint_extern_crate_not_idiomatic = `extern crate` is not idiomatic in the new edi lint_extern_without_abi = extern declarations without an explicit ABI are deprecated .label = ABI should be specified here - .help = the default ABI is {$default_abi} + .suggestion = explicitly specify the {$default_abi} ABI lint_for_loops_over_fallibles = for loop over {$article} `{$ref_prefix}{$ty}`. This is more readably written as an `if let` statement diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 000f4b697bd68..38e52570e53e6 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -2738,11 +2738,9 @@ pub(crate) struct PatternsInFnsWithoutBodySub { #[derive(LintDiagnostic)] #[diag(lint_extern_without_abi)] -#[help] pub(crate) struct MissingAbi { - #[label] + #[suggestion(code = "extern \"{default_abi}\"", applicability = "machine-applicable")] pub span: Span, - pub default_abi: &'static str, } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 36733726564fb..6b4e2d0f4e2f5 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1194,6 +1194,7 @@ impl<'a> Parser<'a> { attrs: &mut AttrVec, mut safety: Safety, ) -> PResult<'a, ItemInfo> { + let extern_span = self.prev_token.uninterpolated_span(); let abi = self.parse_abi(); // ABI? // FIXME: This recovery should be tested better. if safety == Safety::Default @@ -1205,6 +1206,7 @@ impl<'a> Parser<'a> { let _ = self.eat_keyword(kw::Unsafe); } let module = ast::ForeignMod { + extern_span, safety, abi, items: self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No))?, From a433ea2518e18f3beda9bfdd11dc104e40eaa9ac Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 30 Oct 2024 13:41:26 +0100 Subject: [PATCH 2/2] Update tests. --- tests/ui/lint/cli-lint-override.forbid_warn.stderr | 3 +-- tests/ui/lint/cli-lint-override.force_warn_deny.stderr | 3 +-- tests/ui/lint/cli-lint-override.warn_deny.stderr | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/ui/lint/cli-lint-override.forbid_warn.stderr b/tests/ui/lint/cli-lint-override.forbid_warn.stderr index d8c75c33b0c56..169be997b48c6 100644 --- a/tests/ui/lint/cli-lint-override.forbid_warn.stderr +++ b/tests/ui/lint/cli-lint-override.forbid_warn.stderr @@ -2,9 +2,8 @@ error: extern declarations without an explicit ABI are deprecated --> $DIR/cli-lint-override.rs:12:1 | LL | extern fn foo() {} - | ^^^^^^^^^^^^^^^ ABI should be specified here + | ^^^^^^ help: explicitly specify the C ABI: `extern "C"` | - = help: the default ABI is C = note: requested on the command line with `-F missing-abi` error: aborting due to 1 previous error diff --git a/tests/ui/lint/cli-lint-override.force_warn_deny.stderr b/tests/ui/lint/cli-lint-override.force_warn_deny.stderr index 779c24c93f245..574f2ca66a420 100644 --- a/tests/ui/lint/cli-lint-override.force_warn_deny.stderr +++ b/tests/ui/lint/cli-lint-override.force_warn_deny.stderr @@ -2,9 +2,8 @@ warning: extern declarations without an explicit ABI are deprecated --> $DIR/cli-lint-override.rs:12:1 | LL | extern fn foo() {} - | ^^^^^^^^^^^^^^^ ABI should be specified here + | ^^^^^^ help: explicitly specify the C ABI: `extern "C"` | - = help: the default ABI is C = note: requested on the command line with `--force-warn missing-abi` warning: 1 warning emitted diff --git a/tests/ui/lint/cli-lint-override.warn_deny.stderr b/tests/ui/lint/cli-lint-override.warn_deny.stderr index 1ba42e9ce3234..bfec37ada95e5 100644 --- a/tests/ui/lint/cli-lint-override.warn_deny.stderr +++ b/tests/ui/lint/cli-lint-override.warn_deny.stderr @@ -2,9 +2,8 @@ error: extern declarations without an explicit ABI are deprecated --> $DIR/cli-lint-override.rs:12:1 | LL | extern fn foo() {} - | ^^^^^^^^^^^^^^^ ABI should be specified here + | ^^^^^^ help: explicitly specify the C ABI: `extern "C"` | - = help: the default ABI is C = note: requested on the command line with `-D missing-abi` error: aborting due to 1 previous error