about summary refs log tree commit diff
diff options
context:
space:
mode:
authorjyn <github@jyn.dev>2024-10-16 01:35:01 -0400
committerjyn <github@jyn.dev>2025-01-20 16:46:00 -0500
commitfda23843337472d03d9d789ce2b90f0efdb06ae0 (patch)
tree8340ece04fdee0f8faf9465db4ab76f0f8beb63e
parent537218afb2b7f6c8ef9793a52b45c73d1dcb4d4c (diff)
downloadrust-fda23843337472d03d9d789ce2b90f0efdb06ae0.tar.gz
rust-fda23843337472d03d9d789ce2b90f0efdb06ae0.zip
warn on unused linker_messages warning attributes
-rw-r--r--compiler/rustc_passes/messages.ftl3
-rw-r--r--compiler/rustc_passes/src/check_attr.rs28
-rw-r--r--compiler/rustc_passes/src/errors.rs2
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--tests/ui/lint/linker-warning-bin.rs6
-rw-r--r--tests/ui/lint/linker-warning.rs9
-rw-r--r--tests/ui/lint/linker-warning.stderr22
7 files changed, 71 insertions, 0 deletions
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index 3ed600a717f..5d9718258b9 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -817,6 +817,9 @@ passes_unused_duplicate =
 passes_unused_empty_lints_note =
     attribute `{$name}` with an empty list has no effect
 
+passes_unused_linker_warnings_note =
+    the `linker_warnings` lint can only be controlled at the root of a crate that needs to be linked
+
 passes_unused_multiple =
     multiple `{$name}` attributes
     .suggestion = remove this attribute
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 1b2b8ac5dd9..7df792c0f79 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -25,6 +25,7 @@ use rustc_middle::traits::ObligationCause;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::{self, TyCtxt, TypingMode};
 use rustc_middle::{bug, span_bug};
+use rustc_session::config::CrateType;
 use rustc_session::lint::builtin::{
     CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, INVALID_MACRO_EXPORT_ARGUMENTS,
     UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES,
@@ -2328,6 +2329,33 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             && item.path == sym::reason
         {
             errors::UnusedNote::NoLints { name: attr.name_or_empty() }
+        } else if matches!(
+            attr.name_or_empty(),
+            sym::allow | sym::warn | sym::deny | sym::forbid | sym::expect
+        ) && let Some(meta) = attr.meta_item_list()
+            && meta.iter().any(|meta| {
+                meta.meta_item().map_or(false, |item| item.path == sym::linker_messages)
+            })
+        {
+            if hir_id != CRATE_HIR_ID {
+                let err = match attr.style {
+                    ast::AttrStyle::Outer => errors::OuterCrateLevelAttr,
+                    ast::AttrStyle::Inner => errors::OuterCrateLevelAttr,
+                };
+                self.tcx.emit_node_span_lint(UNUSED_ATTRIBUTES, hir_id, attr.span, err);
+                return;
+            } else {
+                let never_needs_link = self
+                    .tcx
+                    .crate_types()
+                    .iter()
+                    .all(|kind| matches!(kind, CrateType::Rlib | CrateType::Staticlib));
+                if never_needs_link {
+                    errors::UnusedNote::LinkerWarningsBinaryCrateOnly
+                } else {
+                    return;
+                }
+            }
         } else if attr.name_or_empty() == sym::default_method_body_is_const {
             errors::UnusedNote::DefaultMethodBodyConst
         } else {
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index c3043ac60aa..89dd10b3e77 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -802,6 +802,8 @@ pub(crate) enum UnusedNote {
     NoLints { name: Symbol },
     #[note(passes_unused_default_method_body_const_note)]
     DefaultMethodBodyConst,
+    #[note(passes_unused_linker_warnings_note)]
+    LinkerWarningsBinaryCrateOnly,
 }
 
 #[derive(LintDiagnostic)]
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index f5ce5dbc9d6..aa22d0f706d 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1189,6 +1189,7 @@ symbols! {
         link_section,
         linkage,
         linker,
+        linker_messages,
         lint_reasons,
         literal,
         load,
diff --git a/tests/ui/lint/linker-warning-bin.rs b/tests/ui/lint/linker-warning-bin.rs
new file mode 100644
index 00000000000..ead0aa002bf
--- /dev/null
+++ b/tests/ui/lint/linker-warning-bin.rs
@@ -0,0 +1,6 @@
+//@ build-pass
+#![crate_type = "bin"]
+#![warn(unused_attributes)]
+#![allow(linker_messages)]
+
+fn main() {}
diff --git a/tests/ui/lint/linker-warning.rs b/tests/ui/lint/linker-warning.rs
new file mode 100644
index 00000000000..10e3f56ab95
--- /dev/null
+++ b/tests/ui/lint/linker-warning.rs
@@ -0,0 +1,9 @@
+//@ check-pass
+#![crate_type = "lib"]
+#![warn(unused_attributes)]
+#![allow(linker_messages)]
+//~^ WARNING unused attribute
+
+#[allow(linker_messages)]
+//~^ WARNING should be an inner attribute
+fn foo() {}
diff --git a/tests/ui/lint/linker-warning.stderr b/tests/ui/lint/linker-warning.stderr
new file mode 100644
index 00000000000..3a2c392fd03
--- /dev/null
+++ b/tests/ui/lint/linker-warning.stderr
@@ -0,0 +1,22 @@
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+  --> $DIR/linker-warning.rs:7:1
+   |
+LL | #[allow(linker_messages)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/linker-warning.rs:3:9
+   |
+LL | #![warn(unused_attributes)]
+   |         ^^^^^^^^^^^^^^^^^
+
+warning: unused attribute
+  --> $DIR/linker-warning.rs:4:1
+   |
+LL | #![allow(linker_messages)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+   |
+   = note: the `linker_warnings` lint can only be controlled at the root of a crate that needs to be linked
+
+warning: 2 warnings emitted
+