From f6d824289347fc0a6318c912b4454a9ba03a57a8 Mon Sep 17 00:00:00 2001 From: Sven Kanoldt Date: Wed, 9 Oct 2024 14:24:15 +0200 Subject: [PATCH] fix: rust-lang/rust#47446 - Add test for issue 47446 - Implement the new lint lint_builtin_mixed_export_name_and_no_mangle - Add suggestion how to fix it --- compiler/rustc_lint/messages.ftl | 5 ++ compiler/rustc_lint/src/builtin.rs | 64 +++++++++++++++++++ compiler/rustc_lint/src/lib.rs | 1 + compiler/rustc_lint/src/lints.rs | 13 ++++ .../mixed_export_name_and_no_mangle.rs | 7 ++ .../mixed_export_name_and_no_mangle.stderr | 17 +++++ 6 files changed, 107 insertions(+) create mode 100644 tests/ui/attributes/mixed_export_name_and_no_mangle.rs create mode 100644 tests/ui/attributes/mixed_export_name_and_no_mangle.stderr diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index d379959487191..234e70c0f001b 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -117,6 +117,11 @@ lint_builtin_missing_debug_impl = lint_builtin_missing_doc = missing documentation for {$article} {$desc} +lint_builtin_mixed_export_name_and_no_mangle = the attribute `export_name` may not be used in combination with `no_mangle` + .label = `export_name` takes precedence + .note = the `no_mangle` attribute is ignored + .suggestion = remove the `no_mangle` attribute + lint_builtin_mutable_transmutes = transmuting &T to &mut T is undefined behavior, even if the reference is unused, consider instead using an UnsafeCell diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 8bd9c899a6286..970e939e7a7f2 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -3035,3 +3035,67 @@ impl EarlyLintPass for SpecialModuleName { } } } + +declare_lint! { + /// The `mixed_export_name_and_no_mangle` lint detects mixed usage of `export_name` and `no_mangle` + /// where `no_mangle` is not used by the compiler. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #[no_mangle] + /// #[export_name = "foo"] + /// pub fn bar() {} + /// + /// fn main() {} + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// The compiler will not use the `no_mangle` attribute when generating the symbol name for the function, + /// as the `export_name` attribute is used instead. This can lead to confusion and is unnecessary. + /// + MIXED_EXPORT_NAME_AND_NO_MANGLE, + Warn, + "mixed usage of export_name and no_mangle, where no_mangle is not used by the compiler" +} + +declare_lint_pass!(MixedExportNameAndNoMangle => [MIXED_EXPORT_NAME_AND_NO_MANGLE]); + +impl MixedExportNameAndNoMangle { + fn report_mixed_export_name_and_no_mangle( + &self, + cx: &EarlyContext<'_>, + span_export_name: Span, + span_no_mangle: Span, + ) { + let decorate = crate::lints::BuiltinMixedExportNameAndNoMangle { + export_name: span_export_name, + no_mangle: span_no_mangle.clone(), + removal_span: span_no_mangle, + }; + cx.emit_span_lint(MIXED_EXPORT_NAME_AND_NO_MANGLE, span_export_name, decorate); + } +} + +impl EarlyLintPass for MixedExportNameAndNoMangle { + fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) { + match it.kind { + ast::ItemKind::Fn(..) | ast::ItemKind::Static(..) => { + let no_mangle = attr::find_by_name(&it.attrs, sym::no_mangle); + let export_name = attr::find_by_name(&it.attrs, sym::export_name); + if let (Some(no_mangle_attr), Some(export_name_attr)) = (no_mangle, export_name) { + self.report_mixed_export_name_and_no_mangle( + cx, + export_name_attr.span, + no_mangle_attr.span, + ); + } + } + + _ => {} + } + } +} diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 81352af3d48fa..6a2096afc2e4f 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -187,6 +187,7 @@ early_lint_methods!( UnusedDocComment: UnusedDocComment, Expr2024: Expr2024, Precedence: Precedence, + MixedExportNameAndNoMangle: MixedExportNameAndNoMangle, ] ] ); diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index a861894a44493..3f5aca24b7d72 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -3053,3 +3053,16 @@ pub(crate) enum MutRefSugg { #[derive(LintDiagnostic)] #[diag(lint_unqualified_local_imports)] pub(crate) struct UnqualifiedLocalImportsDiag {} + +#[derive(LintDiagnostic)] +#[diag(lint_builtin_mixed_export_name_and_no_mangle)] +pub(crate) struct BuiltinMixedExportNameAndNoMangle { + #[label] + pub export_name: Span, + + #[note] + pub no_mangle: Span, + + #[suggestion(style = "verbose", code = "", applicability = "machine-applicable")] + pub removal_span: Span, +} diff --git a/tests/ui/attributes/mixed_export_name_and_no_mangle.rs b/tests/ui/attributes/mixed_export_name_and_no_mangle.rs new file mode 100644 index 0000000000000..63ec213d00a4c --- /dev/null +++ b/tests/ui/attributes/mixed_export_name_and_no_mangle.rs @@ -0,0 +1,7 @@ +// issue: rust-lang/rust#47446 + +#[no_mangle] +#[export_name = "foo"] +pub fn bar() {} + +fn main() {} diff --git a/tests/ui/attributes/mixed_export_name_and_no_mangle.stderr b/tests/ui/attributes/mixed_export_name_and_no_mangle.stderr new file mode 100644 index 0000000000000..4cb92245eddcc --- /dev/null +++ b/tests/ui/attributes/mixed_export_name_and_no_mangle.stderr @@ -0,0 +1,17 @@ +warning: the attribute `export_name` may not be used in combination with `no_mangle` + --> $DIR/E47446.rs:2:1 + | +LL | #[export_name = "foo"] + | ^^^^^^^^^^^^^^^^^^^^^^ `export_name` takes precedence + | + = note: when `export_name` is used `no_mangle` is ignored +note: the `no_mangle` attribute is ignored + --> $DIR/E47446.rs:1:1 + | +LL | #[no_mangle] + | ^^^^^^^^^^^^ + = note: `#[warn(mixed_export_name_and_no_mangle)]` on by default +help: remove the `no_mangle` attribute + | +LL - #[no_mangle] + |