Rollup merge of #132357 - m-ou-se:explicit-abi, r=compiler-errors

Improve missing_abi lint

This is for the migration lint for https://github.com/rust-lang/rfcs/pull/3722

It is not yet marked as an edition migration lint, because `Edition2027` doesn't exist yet.

The lint now includes a machine applicable suggestion:

```
warning: extern declarations without an explicit ABI are deprecated
 --> src/main.rs:3:1
  |
3 | extern fn a() {}
  | ^^^^^^ help: explicitly specify the C ABI: `extern "C"`
  |
```
This commit is contained in:
Jubilee 2024-10-31 17:50:41 -07:00 committed by GitHub
commit 6b0c8cfedc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 17 additions and 19 deletions

View File

@ -2810,6 +2810,8 @@ pub struct ModSpans {
/// E.g., `extern { .. }` or `extern "C" { .. }`. /// E.g., `extern { .. }` or `extern "C" { .. }`.
#[derive(Clone, Encodable, Decodable, Debug)] #[derive(Clone, Encodable, Decodable, Debug)]
pub struct ForeignMod { pub struct ForeignMod {
/// Span of the `extern` keyword.
pub extern_span: Span,
/// `unsafe` keyword accepted syntactically for macro DSLs, but not /// `unsafe` keyword accepted syntactically for macro DSLs, but not
/// semantically by Rust. /// semantically by Rust.
pub safety: Safety, pub safety: Safety,

View File

@ -525,7 +525,7 @@ pub fn walk_ty<T: MutVisitor>(vis: &mut T, ty: &mut P<Ty>) {
} }
fn walk_foreign_mod<T: MutVisitor>(vis: &mut T, foreign_mod: &mut ForeignMod) { fn walk_foreign_mod<T: MutVisitor>(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); visit_safety(vis, safety);
items.flat_map_in_place(|item| vis.flat_map_foreign_item(item)); items.flat_map_in_place(|item| vis.flat_map_foreign_item(item));
} }

View File

@ -366,7 +366,7 @@ fn walk<'a, V: Visitor<'a>>(
} }
ModKind::Unloaded => {} ModKind::Unloaded => {}
}, },
ItemKind::ForeignMod(ForeignMod { safety: _, abi: _, items }) => { ItemKind::ForeignMod(ForeignMod { extern_span: _, safety: _, abi: _, items }) => {
walk_list!(visitor, visit_foreign_item, items); walk_list!(visitor, visit_foreign_item, items);
} }
ItemKind::GlobalAsm(asm) => try_visit!(visitor.visit_inline_asm(asm)), ItemKind::GlobalAsm(asm) => try_visit!(visitor.visit_inline_asm(asm)),

View File

@ -677,9 +677,8 @@ fn visit_ty_common(&mut self, ty: &'a Ty) {
Self::check_decl_no_pat(&bfty.decl, |span, _, _| { Self::check_decl_no_pat(&bfty.decl, |span, _, _| {
self.dcx().emit_err(errors::PatternFnPointer { span }); self.dcx().emit_err(errors::PatternFnPointer { span });
}); });
if let Extern::Implicit(_) = bfty.ext { if let Extern::Implicit(extern_span) = bfty.ext {
let sig_span = self.sess.source_map().next_point(ty.span.shrink_to_lo()); self.maybe_lint_missing_abi(extern_span, ty.id);
self.maybe_lint_missing_abi(sig_span, ty.id);
} }
} }
TyKind::TraitObject(bounds, ..) => { TyKind::TraitObject(bounds, ..) => {
@ -953,7 +952,7 @@ fn visit_item(&mut self, item: &'a Item) {
walk_list!(self, visit_attribute, &item.attrs); walk_list!(self, visit_attribute, &item.attrs);
return; // Avoid visiting again. return; // Avoid visiting again.
} }
ItemKind::ForeignMod(ForeignMod { abi, safety, .. }) => { ItemKind::ForeignMod(ForeignMod { extern_span, abi, safety, .. }) => {
self.with_in_extern_mod(*safety, |this| { self.with_in_extern_mod(*safety, |this| {
let old_item = mem::replace(&mut this.extern_mod, Some(item.span)); let old_item = mem::replace(&mut this.extern_mod, Some(item.span));
this.visibility_not_permitted( this.visibility_not_permitted(
@ -977,7 +976,7 @@ fn visit_item(&mut self, item: &'a Item) {
} }
if abi.is_none() { 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); visit::walk_item(this, item);
this.extern_mod = old_item; this.extern_mod = old_item;
@ -1350,13 +1349,13 @@ fn visit_fn(&mut self, fk: FnKind<'a>, span: Span, id: NodeId) {
if let FnKind::Fn( if let FnKind::Fn(
_, _,
_, _,
FnSig { span: sig_span, header: FnHeader { ext: Extern::Implicit(_), .. }, .. }, FnSig { header: FnHeader { ext: Extern::Implicit(extern_span), .. }, .. },
_, _,
_, _,
_, _,
) = fk ) = fk
{ {
self.maybe_lint_missing_abi(*sig_span, id); self.maybe_lint_missing_abi(*extern_span, id);
} }
// Functions without bodies cannot have patterns. // Functions without bodies cannot have patterns.

View File

@ -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 lint_extern_without_abi = extern declarations without an explicit ABI are deprecated
.label = ABI should be specified here .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 = lint_for_loops_over_fallibles =
for loop over {$article} `{$ref_prefix}{$ty}`. This is more readably written as an `if let` statement for loop over {$article} `{$ref_prefix}{$ty}`. This is more readably written as an `if let` statement

View File

@ -2738,11 +2738,9 @@ pub(crate) struct PatternsInFnsWithoutBodySub {
#[derive(LintDiagnostic)] #[derive(LintDiagnostic)]
#[diag(lint_extern_without_abi)] #[diag(lint_extern_without_abi)]
#[help]
pub(crate) struct MissingAbi { pub(crate) struct MissingAbi {
#[label] #[suggestion(code = "extern \"{default_abi}\"", applicability = "machine-applicable")]
pub span: Span, pub span: Span,
pub default_abi: &'static str, pub default_abi: &'static str,
} }

View File

@ -1194,6 +1194,7 @@ fn parse_item_foreign_mod(
attrs: &mut AttrVec, attrs: &mut AttrVec,
mut safety: Safety, mut safety: Safety,
) -> PResult<'a, ItemInfo> { ) -> PResult<'a, ItemInfo> {
let extern_span = self.prev_token.uninterpolated_span();
let abi = self.parse_abi(); // ABI? let abi = self.parse_abi(); // ABI?
// FIXME: This recovery should be tested better. // FIXME: This recovery should be tested better.
if safety == Safety::Default if safety == Safety::Default
@ -1205,6 +1206,7 @@ fn parse_item_foreign_mod(
let _ = self.eat_keyword(kw::Unsafe); let _ = self.eat_keyword(kw::Unsafe);
} }
let module = ast::ForeignMod { let module = ast::ForeignMod {
extern_span,
safety, safety,
abi, abi,
items: self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No))?, items: self.parse_item_list(attrs, |p| p.parse_foreign_item(ForceCollect::No))?,

View File

@ -2,9 +2,8 @@ error: extern declarations without an explicit ABI are deprecated
--> $DIR/cli-lint-override.rs:12:1 --> $DIR/cli-lint-override.rs:12:1
| |
LL | extern fn foo() {} 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` = note: requested on the command line with `-F missing-abi`
error: aborting due to 1 previous error error: aborting due to 1 previous error

View File

@ -2,9 +2,8 @@ warning: extern declarations without an explicit ABI are deprecated
--> $DIR/cli-lint-override.rs:12:1 --> $DIR/cli-lint-override.rs:12:1
| |
LL | extern fn foo() {} 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` = note: requested on the command line with `--force-warn missing-abi`
warning: 1 warning emitted warning: 1 warning emitted

View File

@ -2,9 +2,8 @@ error: extern declarations without an explicit ABI are deprecated
--> $DIR/cli-lint-override.rs:12:1 --> $DIR/cli-lint-override.rs:12:1
| |
LL | extern fn foo() {} 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` = note: requested on the command line with `-D missing-abi`
error: aborting due to 1 previous error error: aborting due to 1 previous error