about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_macros/src/session_diagnostic.rs1
-rw-r--r--compiler/rustc_passes/src/check_attr.rs35
2 files changed, 34 insertions, 2 deletions
diff --git a/compiler/rustc_macros/src/session_diagnostic.rs b/compiler/rustc_macros/src/session_diagnostic.rs
index 9a7784ca72f..f29683e5e1d 100644
--- a/compiler/rustc_macros/src/session_diagnostic.rs
+++ b/compiler/rustc_macros/src/session_diagnostic.rs
@@ -587,7 +587,6 @@ impl<'a> SessionDiagnosticDeriveBuilder<'a> {
         // next call to `it.next()` retrieves the next character.
         while let Some(c) = it.next() {
             if c == '{' && *it.peek().unwrap_or(&'\0') != '{' {
-                #[must_use]
                 let mut eat_argument = || -> Option<String> {
                     let mut result = String::new();
                     // Format specifiers look like
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 6e4907fe518..39e7a3019a5 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -1111,7 +1111,7 @@ impl CheckAttrVisitor<'_> {
     }
 
     /// Warns against some misuses of `#[must_use]`
-    fn check_must_use(&self, hir_id: HirId, attr: &Attribute, span: Span, _target: Target) -> bool {
+    fn check_must_use(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool {
         let node = self.tcx.hir().get(hir_id);
         if let Some(fn_node) = node.fn_kind() {
             if let rustc_hir::IsAsync::Async = fn_node.asyncness() {
@@ -1131,6 +1131,39 @@ impl CheckAttrVisitor<'_> {
             }
         }
 
+        if !matches!(
+            target,
+            Target::Fn
+                | Target::Enum
+                | Target::Struct
+                | Target::Union
+                | Target::Method(_)
+                | Target::ForeignFn
+                // `impl Trait` in return position can trip
+                // `unused_must_use` if `Trait` is marked as
+                // `#[must_use]`
+                | Target::Trait
+        ) {
+            let article = match target {
+                Target::ExternCrate
+                | Target::OpaqueTy
+                | Target::Enum
+                | Target::Impl
+                | Target::Expression
+                | Target::Arm
+                | Target::AssocConst
+                | Target::AssocTy => "an",
+                _ => "a",
+            };
+
+            self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
+                lint.build(&format!(
+                    "`#[must_use]` has no effect when applied to {article} {target}"
+                ))
+                .emit();
+            });
+        }
+
         // For now, its always valid
         true
     }