about summary refs log tree commit diff
path: root/compiler/rustc_passes/src
diff options
context:
space:
mode:
authorZalathar <Zalathar@users.noreply.github.com>2024-12-25 14:57:21 +1100
committerZalathar <Zalathar@users.noreply.github.com>2024-12-25 16:17:09 +1100
commit399620939844d7b2e4a93e450f8c578960d0b6f2 (patch)
treeb83ad750522f061f1dae7093fdb8c0860f0bded8 /compiler/rustc_passes/src
parent9124662da3e0d573703c9bb07d5e3cf8d06f1b20 (diff)
downloadrust-399620939844d7b2e4a93e450f8c578960d0b6f2.tar.gz
rust-399620939844d7b2e4a93e450f8c578960d0b6f2.zip
Overhaul error messages for disallowed coverage attributes
Diffstat (limited to 'compiler/rustc_passes/src')
-rw-r--r--compiler/rustc_passes/src/check_attr.rs25
-rw-r--r--compiler/rustc_passes/src/errors.rs16
2 files changed, 31 insertions, 10 deletions
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 8cf20a378d4..12f715a0fe4 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -432,21 +432,34 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
 
     /// Checks that `#[coverage(..)]` is applied to a function/closure/method,
     /// or to an impl block or module.
-    fn check_coverage(&self, attr: &Attribute, span: Span, target: Target) {
+    fn check_coverage(&self, attr: &Attribute, target_span: Span, target: Target) {
+        let mut not_fn_impl_mod = None;
+        let mut no_body = None;
+
         match target {
             Target::Fn
             | Target::Closure
             | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent)
             | Target::Impl
-            | Target::Mod => {}
+            | Target::Mod => return,
+
+            // These are "functions", but they aren't allowed because they don't
+            // have a body, so the usual explanation would be confusing.
+            Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => {
+                no_body = Some(target_span);
+            }
 
             _ => {
-                self.dcx().emit_err(errors::CoverageNotFnOrClosure {
-                    attr_span: attr.span,
-                    defn_span: span,
-                });
+                not_fn_impl_mod = Some(target_span);
             }
         }
+
+        self.dcx().emit_err(errors::CoverageAttributeNotAllowed {
+            attr_span: attr.span,
+            not_fn_impl_mod,
+            no_body,
+            help: (),
+        });
     }
 
     /// Checks that `#[optimize(..)]` is applied to a function/closure/method,
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 163325f2a3c..d95fa5db0ce 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -71,13 +71,21 @@ pub(crate) struct InlineNotFnOrClosure {
     pub defn_span: Span,
 }
 
+/// "coverage attribute not allowed here"
 #[derive(Diagnostic)]
-#[diag(passes_coverage_not_fn_or_closure, code = E0788)]
-pub(crate) struct CoverageNotFnOrClosure {
+#[diag(passes_coverage_attribute_not_allowed, code = E0788)]
+pub(crate) struct CoverageAttributeNotAllowed {
     #[primary_span]
     pub attr_span: Span,
-    #[label]
-    pub defn_span: Span,
+    /// "not a function, impl block, or module"
+    #[label(passes_not_fn_impl_mod)]
+    pub not_fn_impl_mod: Option<Span>,
+    /// "function has no body"
+    #[label(passes_no_body)]
+    pub no_body: Option<Span>,
+    /// "coverage attribute can be applied to a function (with body), impl block, or module"
+    #[help]
+    pub help: (),
 }
 
 #[derive(Diagnostic)]