about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSasha Pourcelot <sasha.pourcelot@protonmail.com>2025-07-13 11:51:22 +0200
committerSasha Pourcelot <sasha.pourcelot@protonmail.com>2025-07-16 15:51:18 +0200
commit4e054fc4c4809a3c1df60ea99077f4d662b79750 (patch)
tree4d2c1b0b6a0b8374aef15d76dcb05df147f35f95
parentf21fbac535ab2c3bc50db20547f4d48477357103 (diff)
downloadrust-4e054fc4c4809a3c1df60ea99077f4d662b79750.tar.gz
rust-4e054fc4c4809a3c1df60ea99077f4d662b79750.zip
Port `#[coverage]` to the new attribute system
-rw-r--r--compiler/rustc_attr_data_structures/src/attributes.rs19
-rw-r--r--compiler/rustc_attr_data_structures/src/encode_cross_crate.rs1
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs41
-rw-r--r--compiler/rustc_attr_parsing/src/context.rs26
-rw-r--r--compiler/rustc_attr_parsing/src/session_diagnostics.rs49
-rw-r--r--compiler/rustc_mir_transform/src/coverage/query.rs32
-rw-r--r--compiler/rustc_parse/src/validate_attr.rs1
-rw-r--r--compiler/rustc_passes/src/check_attr.rs8
-rw-r--r--tests/ui/attributes/malformed-attrs.stderr26
-rw-r--r--tests/ui/coverage-attr/bad-attr-ice.feat.stderr7
-rw-r--r--tests/ui/coverage-attr/bad-attr-ice.nofeat.stderr27
-rw-r--r--tests/ui/coverage-attr/bad-syntax.stderr134
-rw-r--r--tests/ui/coverage-attr/name-value.rs7
-rw-r--r--tests/ui/coverage-attr/name-value.stderr179
-rw-r--r--tests/ui/coverage-attr/subword.stderr33
-rw-r--r--tests/ui/coverage-attr/word-only.rs7
-rw-r--r--tests/ui/coverage-attr/word-only.stderr185
17 files changed, 377 insertions, 405 deletions
diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs
index 3dedeb1b372..24f52d6f500 100644
--- a/compiler/rustc_attr_data_structures/src/attributes.rs
+++ b/compiler/rustc_attr_data_structures/src/attributes.rs
@@ -110,6 +110,22 @@ pub enum DeprecatedSince {
     Err,
 }
 
+#[derive(
+    Copy,
+    Debug,
+    Eq,
+    PartialEq,
+    Encodable,
+    Decodable,
+    Clone,
+    HashStable_Generic,
+    PrintAttribute
+)]
+pub enum CoverageStatus {
+    On,
+    Off,
+}
+
 impl Deprecation {
     /// Whether an item marked with #[deprecated(since = "X")] is currently
     /// deprecated (i.e., whether X is not greater than the current rustc
@@ -274,6 +290,9 @@ pub enum AttributeKind {
     /// Represents `#[const_trait]`.
     ConstTrait(Span),
 
+    /// Represents `#[coverage]`.
+    Coverage(Span, CoverageStatus),
+
     ///Represents `#[rustc_deny_explicit_impl]`.
     DenyExplicitImpl(Span),
 
diff --git a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs
index 3e2dc0a15b2..8105e4fb125 100644
--- a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs
+++ b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs
@@ -28,6 +28,7 @@ impl AttributeKind {
             ConstStability { .. } => Yes,
             ConstStabilityIndirect => No,
             ConstTrait(..) => No,
+            Coverage(..) => No,
             DenyExplicitImpl(..) => No,
             Deprecation { .. } => Yes,
             DoNotImplementViaObject(..) => No,
diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
index 34d9b048348..3e542771d58 100644
--- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
@@ -1,4 +1,4 @@
-use rustc_attr_data_structures::{AttributeKind, OptimizeAttr, UsedBy};
+use rustc_attr_data_structures::{AttributeKind, CoverageStatus, OptimizeAttr, UsedBy};
 use rustc_feature::{AttributeTemplate, template};
 use rustc_session::parse::feature_err;
 use rustc_span::{Span, Symbol, sym};
@@ -52,6 +52,45 @@ impl<S: Stage> NoArgsAttributeParser<S> for ColdParser {
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::Cold;
 }
 
+pub(crate) struct CoverageParser;
+
+impl<S: Stage> SingleAttributeParser<S> for CoverageParser {
+    const PATH: &[Symbol] = &[sym::coverage];
+    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
+    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const TEMPLATE: AttributeTemplate = template!(OneOf: &[sym::off, sym::on]);
+
+    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
+        let Some(args) = args.list() else {
+            cx.expected_specific_argument_and_list(cx.attr_span, vec!["on", "off"]);
+            return None;
+        };
+
+        let Some(arg) = args.single() else {
+            cx.expected_single_argument(args.span);
+            return None;
+        };
+
+        let fail_incorrect_argument = |span| cx.expected_specific_argument(span, vec!["on", "off"]);
+
+        let Some(arg) = arg.meta_item() else {
+            fail_incorrect_argument(args.span);
+            return None;
+        };
+
+        let status = match arg.path().word_sym() {
+            Some(sym::off) => CoverageStatus::Off,
+            Some(sym::on) => CoverageStatus::On,
+            None | Some(_) => {
+                fail_incorrect_argument(arg.span());
+                return None;
+            }
+        };
+
+        Some(AttributeKind::Coverage(cx.attr_span, status))
+    }
+}
+
 pub(crate) struct ExportNameParser;
 
 impl<S: Stage> SingleAttributeParser<S> for ExportNameParser {
diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs
index 567341d1517..043a0524269 100644
--- a/compiler/rustc_attr_parsing/src/context.rs
+++ b/compiler/rustc_attr_parsing/src/context.rs
@@ -15,8 +15,9 @@ use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym};
 
 use crate::attributes::allow_unstable::{AllowConstFnUnstableParser, AllowInternalUnstableParser};
 use crate::attributes::codegen_attrs::{
-    ColdParser, ExportNameParser, NakedParser, NoMangleParser, OmitGdbPrettyPrinterSectionParser,
-    OptimizeParser, TargetFeatureParser, TrackCallerParser, UsedParser,
+    ColdParser, CoverageParser, ExportNameParser, NakedParser, NoMangleParser,
+    OmitGdbPrettyPrinterSectionParser, OptimizeParser, TargetFeatureParser, TrackCallerParser,
+    UsedParser,
 };
 use crate::attributes::confusables::ConfusablesParser;
 use crate::attributes::deprecation::DeprecationParser;
@@ -136,6 +137,7 @@ attribute_parsers!(
         // tidy-alphabetical-end
 
         // tidy-alphabetical-start
+        Single<CoverageParser>,
         Single<DeprecationParser>,
         Single<DummyParser>,
         Single<ExportNameParser>,
@@ -449,6 +451,25 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
             reason: AttributeParseErrorReason::ExpectedSpecificArgument {
                 possibilities,
                 strings: false,
+                list: false,
+            },
+        })
+    }
+
+    pub(crate) fn expected_specific_argument_and_list(
+        &self,
+        span: Span,
+        possibilities: Vec<&'static str>,
+    ) -> ErrorGuaranteed {
+        self.emit_err(AttributeParseError {
+            span,
+            attr_span: self.attr_span,
+            template: self.template.clone(),
+            attribute: self.attr_path.clone(),
+            reason: AttributeParseErrorReason::ExpectedSpecificArgument {
+                possibilities,
+                strings: false,
+                list: true,
             },
         })
     }
@@ -466,6 +487,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
             reason: AttributeParseErrorReason::ExpectedSpecificArgument {
                 possibilities,
                 strings: true,
+                list: false,
             },
         })
     }
diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs
index 97bf3d1c549..67dac8da384 100644
--- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs
+++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs
@@ -525,7 +525,9 @@ pub(crate) struct LinkOrdinalOutOfRange {
 
 pub(crate) enum AttributeParseErrorReason {
     ExpectedNoArgs,
-    ExpectedStringLiteral { byte_string: Option<Span> },
+    ExpectedStringLiteral {
+        byte_string: Option<Span>,
+    },
     ExpectedIntegerLiteral,
     ExpectedAtLeastOneArgument,
     ExpectedSingleArgument,
@@ -533,7 +535,12 @@ pub(crate) enum AttributeParseErrorReason {
     UnexpectedLiteral,
     ExpectedNameValue(Option<Symbol>),
     DuplicateKey(Symbol),
-    ExpectedSpecificArgument { possibilities: Vec<&'static str>, strings: bool },
+    ExpectedSpecificArgument {
+        possibilities: Vec<&'static str>,
+        strings: bool,
+        /// Should we tell the user to write a list when they didn't?
+        list: bool,
+    },
 }
 
 pub(crate) struct AttributeParseError {
@@ -607,7 +614,11 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError {
                     format!("expected this to be of the form `{name} = \"...\"`"),
                 );
             }
-            AttributeParseErrorReason::ExpectedSpecificArgument { possibilities, strings } => {
+            AttributeParseErrorReason::ExpectedSpecificArgument {
+                possibilities,
+                strings,
+                list: false,
+            } => {
                 let quote = if strings { '"' } else { '`' };
                 match possibilities.as_slice() {
                     &[] => {}
@@ -633,6 +644,38 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError {
                     }
                 }
             }
+            AttributeParseErrorReason::ExpectedSpecificArgument {
+                possibilities,
+                strings,
+                list: true,
+            } => {
+                let quote = if strings { '"' } else { '`' };
+                match possibilities.as_slice() {
+                    &[] => {}
+                    &[x] => {
+                        diag.span_label(
+                            self.span,
+                            format!(
+                                "this attribute is only valid with {quote}{x}{quote} as an argument"
+                            ),
+                        );
+                    }
+                    [first, second] => {
+                        diag.span_label(self.span, format!("this attribute is only valid with either {quote}{first}{quote} or {quote}{second}{quote} as an argument"));
+                    }
+                    [first @ .., second_to_last, last] => {
+                        let mut res = String::new();
+                        for i in first {
+                            res.push_str(&format!("{quote}{i}{quote}, "));
+                        }
+                        res.push_str(&format!(
+                            "{quote}{second_to_last}{quote} or {quote}{last}{quote}"
+                        ));
+
+                        diag.span_label(self.span, format!("this attribute is only valid with one of the following arguments: {res}"));
+                    }
+                }
+            }
         }
 
         let suggestions = self.template.suggestions(false, &name);
diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs
index ccf76dc7108..986c001de5e 100644
--- a/compiler/rustc_mir_transform/src/coverage/query.rs
+++ b/compiler/rustc_mir_transform/src/coverage/query.rs
@@ -1,3 +1,4 @@
+use rustc_attr_data_structures::{AttributeKind, CoverageStatus, find_attr};
 use rustc_index::bit_set::DenseBitSet;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::mir::coverage::{BasicCoverageBlock, CoverageIdsInfo, CoverageKind, MappingKind};
@@ -5,7 +6,6 @@ use rustc_middle::mir::{Body, Statement, StatementKind};
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_middle::util::Providers;
 use rustc_span::def_id::LocalDefId;
-use rustc_span::sym;
 use tracing::trace;
 
 use crate::coverage::counters::node_flow::make_node_counters;
@@ -58,26 +58,20 @@ fn is_eligible_for_coverage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
 /// Query implementation for `coverage_attr_on`.
 fn coverage_attr_on(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
     // Check for annotations directly on this def.
-    if let Some(attr) = tcx.get_attr(def_id, sym::coverage) {
-        match attr.meta_item_list().as_deref() {
-            Some([item]) if item.has_name(sym::off) => return false,
-            Some([item]) if item.has_name(sym::on) => return true,
-            Some(_) | None => {
-                // Other possibilities should have been rejected by `rustc_parse::validate_attr`.
-                // Use `span_delayed_bug` to avoid an ICE in failing builds (#127880).
-                tcx.dcx().span_delayed_bug(attr.span(), "unexpected value of coverage attribute");
-            }
+    if let Some(coverage_status) =
+        find_attr!(tcx.get_all_attrs(def_id), AttributeKind::Coverage(_, status) => status)
+    {
+        *coverage_status == CoverageStatus::On
+    } else {
+        match tcx.opt_local_parent(def_id) {
+            // Check the parent def (and so on recursively) until we find an
+            // enclosing attribute or reach the crate root.
+            Some(parent) => tcx.coverage_attr_on(parent),
+            // We reached the crate root without seeing a coverage attribute, so
+            // allow coverage instrumentation by default.
+            None => true,
         }
     }
-
-    match tcx.opt_local_parent(def_id) {
-        // Check the parent def (and so on recursively) until we find an
-        // enclosing attribute or reach the crate root.
-        Some(parent) => tcx.coverage_attr_on(parent),
-        // We reached the crate root without seeing a coverage attribute, so
-        // allow coverage instrumentation by default.
-        None => true,
-    }
 }
 
 /// Query implementation for `coverage_ids_info`.
diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs
index 783d79d978a..a476f0db37e 100644
--- a/compiler/rustc_parse/src/validate_attr.rs
+++ b/compiler/rustc_parse/src/validate_attr.rs
@@ -318,6 +318,7 @@ pub fn check_builtin_meta_item(
                 | sym::rustc_layout_scalar_valid_range_end
                 | sym::no_implicit_prelude
                 | sym::automatically_derived
+                | sym::coverage
         ) {
             return;
         }
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 2009ddc1e2d..810472eb2de 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -285,6 +285,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                 &Attribute::Parsed(AttributeKind::StdInternalSymbol(attr_span)) => {
                     self.check_rustc_std_internal_symbol(attr_span, span, target)
                 }
+                &Attribute::Parsed(AttributeKind::Coverage(attr_span, _)) => {
+                    self.check_coverage(attr_span, span, target)
+                }
                 Attribute::Unparsed(attr_item) => {
                     style = Some(attr_item.style);
                     match attr.path().as_slice() {
@@ -294,7 +297,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                         [sym::diagnostic, sym::on_unimplemented, ..] => {
                             self.check_diagnostic_on_unimplemented(attr.span(), hir_id, target)
                         }
-                        [sym::coverage, ..] => self.check_coverage(attr, span, target),
                         [sym::no_sanitize, ..] => {
                             self.check_no_sanitize(attr, span, target)
                         }
@@ -585,7 +587,7 @@ 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, target_span: Span, target: Target) {
+    fn check_coverage(&self, attr_span: Span, target_span: Span, target: Target) {
         let mut not_fn_impl_mod = None;
         let mut no_body = None;
 
@@ -608,7 +610,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         }
 
         self.dcx().emit_err(errors::CoverageAttributeNotAllowed {
-            attr_span: attr.span(),
+            attr_span,
             not_fn_impl_mod,
             no_body,
             help: (),
diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr
index 56f2be353e7..0d0c338d302 100644
--- a/tests/ui/attributes/malformed-attrs.stderr
+++ b/tests/ui/attributes/malformed-attrs.stderr
@@ -37,19 +37,6 @@ error: malformed `crate_name` attribute input
 LL | #[crate_name]
    | ^^^^^^^^^^^^^ help: must be of the form: `#[crate_name = "name"]`
 
-error: malformed `coverage` attribute input
-  --> $DIR/malformed-attrs.rs:90:1
-   |
-LL | #[coverage]
-   | ^^^^^^^^^^^
-   |
-help: the following are the possible correct uses
-   |
-LL | #[coverage(off)]
-   |           +++++
-LL | #[coverage(on)]
-   |           ++++
-
 error: malformed `no_sanitize` attribute input
   --> $DIR/malformed-attrs.rs:92:1
    |
@@ -460,6 +447,19 @@ error[E0539]: malformed `link_section` attribute input
 LL | #[link_section]
    | ^^^^^^^^^^^^^^^ help: must be of the form: `#[link_section = "name"]`
 
+error[E0539]: malformed `coverage` attribute input
+  --> $DIR/malformed-attrs.rs:90:1
+   |
+LL | #[coverage]
+   | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
+   |
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL | #[coverage(off)]
+   |           +++++
+LL | #[coverage(on)]
+   |           ++++
+
 error[E0565]: malformed `no_implicit_prelude` attribute input
   --> $DIR/malformed-attrs.rs:97:1
    |
diff --git a/tests/ui/coverage-attr/bad-attr-ice.feat.stderr b/tests/ui/coverage-attr/bad-attr-ice.feat.stderr
index dc84394fe3c..5a003af42da 100644
--- a/tests/ui/coverage-attr/bad-attr-ice.feat.stderr
+++ b/tests/ui/coverage-attr/bad-attr-ice.feat.stderr
@@ -1,10 +1,10 @@
-error: malformed `coverage` attribute input
+error[E0539]: malformed `coverage` attribute input
   --> $DIR/bad-attr-ice.rs:11:1
    |
 LL | #[coverage]
-   | ^^^^^^^^^^^
+   | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL | #[coverage(off)]
    |           +++++
@@ -13,3 +13,4 @@ LL | #[coverage(on)]
 
 error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0539`.
diff --git a/tests/ui/coverage-attr/bad-attr-ice.nofeat.stderr b/tests/ui/coverage-attr/bad-attr-ice.nofeat.stderr
index 49b8974bfdf..4501e5e9dc8 100644
--- a/tests/ui/coverage-attr/bad-attr-ice.nofeat.stderr
+++ b/tests/ui/coverage-attr/bad-attr-ice.nofeat.stderr
@@ -1,26 +1,27 @@
-error: malformed `coverage` attribute input
+error[E0658]: the `#[coverage]` attribute is an experimental feature
   --> $DIR/bad-attr-ice.rs:11:1
    |
 LL | #[coverage]
    | ^^^^^^^^^^^
    |
-help: the following are the possible correct uses
-   |
-LL | #[coverage(off)]
-   |           +++++
-LL | #[coverage(on)]
-   |           ++++
+   = note: see issue #84605 <https://github.com/rust-lang/rust/issues/84605> for more information
+   = help: add `#![feature(coverage_attribute)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: the `#[coverage]` attribute is an experimental feature
+error[E0539]: malformed `coverage` attribute input
   --> $DIR/bad-attr-ice.rs:11:1
    |
 LL | #[coverage]
-   | ^^^^^^^^^^^
+   | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
    |
-   = note: see issue #84605 <https://github.com/rust-lang/rust/issues/84605> for more information
-   = help: add `#![feature(coverage_attribute)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL | #[coverage(off)]
+   |           +++++
+LL | #[coverage(on)]
+   |           ++++
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0658`.
+Some errors have detailed explanations: E0539, E0658.
+For more information about an error, try `rustc --explain E0539`.
diff --git a/tests/ui/coverage-attr/bad-syntax.stderr b/tests/ui/coverage-attr/bad-syntax.stderr
index fa500b54209..927f61da08d 100644
--- a/tests/ui/coverage-attr/bad-syntax.stderr
+++ b/tests/ui/coverage-attr/bad-syntax.stderr
@@ -1,23 +1,59 @@
-error: malformed `coverage` attribute input
+error: expected identifier, found `,`
+  --> $DIR/bad-syntax.rs:44:12
+   |
+LL | #[coverage(,off)]
+   |            ^ expected identifier
+   |
+help: remove this comma
+   |
+LL - #[coverage(,off)]
+LL + #[coverage(off)]
+   |
+
+error: multiple `coverage` attributes
+  --> $DIR/bad-syntax.rs:9:1
+   |
+LL | #[coverage(off)]
+   | ^^^^^^^^^^^^^^^^ help: remove this attribute
+   |
+note: attribute also specified here
+  --> $DIR/bad-syntax.rs:10:1
+   |
+LL | #[coverage(off)]
+   | ^^^^^^^^^^^^^^^^
+
+error: multiple `coverage` attributes
+  --> $DIR/bad-syntax.rs:13:1
+   |
+LL | #[coverage(off)]
+   | ^^^^^^^^^^^^^^^^ help: remove this attribute
+   |
+note: attribute also specified here
+  --> $DIR/bad-syntax.rs:14:1
+   |
+LL | #[coverage(on)]
+   | ^^^^^^^^^^^^^^^
+
+error[E0539]: malformed `coverage` attribute input
   --> $DIR/bad-syntax.rs:17:1
    |
 LL | #[coverage]
-   | ^^^^^^^^^^^
+   | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL | #[coverage(off)]
    |           +++++
 LL | #[coverage(on)]
    |           ++++
 
-error: malformed `coverage` attribute input
+error[E0539]: malformed `coverage` attribute input
   --> $DIR/bad-syntax.rs:20:1
    |
 LL | #[coverage = true]
-   | ^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL - #[coverage = true]
 LL + #[coverage(off)]
@@ -26,26 +62,30 @@ LL - #[coverage = true]
 LL + #[coverage(on)]
    |
 
-error: malformed `coverage` attribute input
+error[E0805]: malformed `coverage` attribute input
   --> $DIR/bad-syntax.rs:23:1
    |
 LL | #[coverage()]
-   | ^^^^^^^^^^^^^
+   | ^^^^^^^^^^--^
+   |           |
+   |           expected a single argument here
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL | #[coverage(off)]
    |            +++
 LL | #[coverage(on)]
    |            ++
 
-error: malformed `coverage` attribute input
+error[E0805]: malformed `coverage` attribute input
   --> $DIR/bad-syntax.rs:26:1
    |
 LL | #[coverage(off, off)]
-   | ^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^----------^
+   |           |
+   |           expected a single argument here
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL - #[coverage(off, off)]
 LL + #[coverage(off)]
@@ -54,13 +94,15 @@ LL - #[coverage(off, off)]
 LL + #[coverage(on)]
    |
 
-error: malformed `coverage` attribute input
+error[E0805]: malformed `coverage` attribute input
   --> $DIR/bad-syntax.rs:29:1
    |
 LL | #[coverage(off, on)]
-   | ^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^---------^
+   |           |
+   |           expected a single argument here
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL - #[coverage(off, on)]
 LL + #[coverage(off)]
@@ -69,13 +111,15 @@ LL - #[coverage(off, on)]
 LL + #[coverage(on)]
    |
 
-error: malformed `coverage` attribute input
+error[E0539]: malformed `coverage` attribute input
   --> $DIR/bad-syntax.rs:32:1
    |
 LL | #[coverage(bogus)]
-   | ^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^-----^^
+   |            |
+   |            valid arguments are `on` or `off`
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL - #[coverage(bogus)]
 LL + #[coverage(off)]
@@ -84,13 +128,15 @@ LL - #[coverage(bogus)]
 LL + #[coverage(on)]
    |
 
-error: malformed `coverage` attribute input
+error[E0805]: malformed `coverage` attribute input
   --> $DIR/bad-syntax.rs:35:1
    |
 LL | #[coverage(bogus, off)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^------------^
+   |           |
+   |           expected a single argument here
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL - #[coverage(bogus, off)]
 LL + #[coverage(off)]
@@ -99,13 +145,15 @@ LL - #[coverage(bogus, off)]
 LL + #[coverage(on)]
    |
 
-error: malformed `coverage` attribute input
+error[E0805]: malformed `coverage` attribute input
   --> $DIR/bad-syntax.rs:38:1
    |
 LL | #[coverage(off, bogus)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^------------^
+   |           |
+   |           expected a single argument here
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL - #[coverage(off, bogus)]
 LL + #[coverage(off)]
@@ -114,41 +162,7 @@ LL - #[coverage(off, bogus)]
 LL + #[coverage(on)]
    |
 
-error: expected identifier, found `,`
-  --> $DIR/bad-syntax.rs:44:12
-   |
-LL | #[coverage(,off)]
-   |            ^ expected identifier
-   |
-help: remove this comma
-   |
-LL - #[coverage(,off)]
-LL + #[coverage(off)]
-   |
-
-error: multiple `coverage` attributes
-  --> $DIR/bad-syntax.rs:9:1
-   |
-LL | #[coverage(off)]
-   | ^^^^^^^^^^^^^^^^ help: remove this attribute
-   |
-note: attribute also specified here
-  --> $DIR/bad-syntax.rs:10:1
-   |
-LL | #[coverage(off)]
-   | ^^^^^^^^^^^^^^^^
-
-error: multiple `coverage` attributes
-  --> $DIR/bad-syntax.rs:13:1
-   |
-LL | #[coverage(off)]
-   | ^^^^^^^^^^^^^^^^ help: remove this attribute
-   |
-note: attribute also specified here
-  --> $DIR/bad-syntax.rs:14:1
-   |
-LL | #[coverage(on)]
-   | ^^^^^^^^^^^^^^^
-
 error: aborting due to 11 previous errors
 
+Some errors have detailed explanations: E0539, E0805.
+For more information about an error, try `rustc --explain E0539`.
diff --git a/tests/ui/coverage-attr/name-value.rs b/tests/ui/coverage-attr/name-value.rs
index ffd9afe2ce1..8171dbbf692 100644
--- a/tests/ui/coverage-attr/name-value.rs
+++ b/tests/ui/coverage-attr/name-value.rs
@@ -20,7 +20,6 @@ mod my_mod_inner {
 
 #[coverage = "off"]
 //~^ ERROR malformed `coverage` attribute input
-//~| ERROR [E0788]
 struct MyStruct;
 
 #[coverage = "off"]
@@ -28,22 +27,18 @@ struct MyStruct;
 impl MyStruct {
     #[coverage = "off"]
     //~^ ERROR malformed `coverage` attribute input
-    //~| ERROR [E0788]
     const X: u32 = 7;
 }
 
 #[coverage = "off"]
 //~^ ERROR malformed `coverage` attribute input
-//~| ERROR [E0788]
 trait MyTrait {
     #[coverage = "off"]
     //~^ ERROR malformed `coverage` attribute input
-    //~| ERROR [E0788]
     const X: u32;
 
     #[coverage = "off"]
     //~^ ERROR malformed `coverage` attribute input
-    //~| ERROR [E0788]
     type T;
 }
 
@@ -52,12 +47,10 @@ trait MyTrait {
 impl MyTrait for MyStruct {
     #[coverage = "off"]
     //~^ ERROR malformed `coverage` attribute input
-    //~| ERROR [E0788]
     const X: u32 = 8;
 
     #[coverage = "off"]
     //~^ ERROR malformed `coverage` attribute input
-    //~| ERROR [E0788]
     type T = ();
 }
 
diff --git a/tests/ui/coverage-attr/name-value.stderr b/tests/ui/coverage-attr/name-value.stderr
index f24db78415e..a838ec5df8e 100644
--- a/tests/ui/coverage-attr/name-value.stderr
+++ b/tests/ui/coverage-attr/name-value.stderr
@@ -1,10 +1,10 @@
-error: malformed `coverage` attribute input
+error[E0539]: malformed `coverage` attribute input
   --> $DIR/name-value.rs:12:1
    |
 LL | #[coverage = "off"]
-   | ^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL - #[coverage = "off"]
 LL + #[coverage(off)]
@@ -13,28 +13,28 @@ LL - #[coverage = "off"]
 LL + #[coverage(on)]
    |
 
-error: malformed `coverage` attribute input
+error[E0539]: malformed `coverage` attribute input
   --> $DIR/name-value.rs:17:5
    |
 LL |     #![coverage = "off"]
-   |     ^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL -     #![coverage = "off"]
-LL +     #![coverage(off)]
+LL +     #[coverage(off)]
    |
 LL -     #![coverage = "off"]
-LL +     #![coverage(on)]
+LL +     #[coverage(on)]
    |
 
-error: malformed `coverage` attribute input
+error[E0539]: malformed `coverage` attribute input
   --> $DIR/name-value.rs:21:1
    |
 LL | #[coverage = "off"]
-   | ^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL - #[coverage = "off"]
 LL + #[coverage(off)]
@@ -43,13 +43,13 @@ LL - #[coverage = "off"]
 LL + #[coverage(on)]
    |
 
-error: malformed `coverage` attribute input
-  --> $DIR/name-value.rs:26:1
+error[E0539]: malformed `coverage` attribute input
+  --> $DIR/name-value.rs:25:1
    |
 LL | #[coverage = "off"]
-   | ^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL - #[coverage = "off"]
 LL + #[coverage(off)]
@@ -58,13 +58,13 @@ LL - #[coverage = "off"]
 LL + #[coverage(on)]
    |
 
-error: malformed `coverage` attribute input
-  --> $DIR/name-value.rs:29:5
+error[E0539]: malformed `coverage` attribute input
+  --> $DIR/name-value.rs:28:5
    |
 LL |     #[coverage = "off"]
-   |     ^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL -     #[coverage = "off"]
 LL +     #[coverage(off)]
@@ -73,13 +73,13 @@ LL -     #[coverage = "off"]
 LL +     #[coverage(on)]
    |
 
-error: malformed `coverage` attribute input
-  --> $DIR/name-value.rs:35:1
+error[E0539]: malformed `coverage` attribute input
+  --> $DIR/name-value.rs:33:1
    |
 LL | #[coverage = "off"]
-   | ^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL - #[coverage = "off"]
 LL + #[coverage(off)]
@@ -88,13 +88,13 @@ LL - #[coverage = "off"]
 LL + #[coverage(on)]
    |
 
-error: malformed `coverage` attribute input
-  --> $DIR/name-value.rs:39:5
+error[E0539]: malformed `coverage` attribute input
+  --> $DIR/name-value.rs:36:5
    |
 LL |     #[coverage = "off"]
-   |     ^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL -     #[coverage = "off"]
 LL +     #[coverage(off)]
@@ -103,13 +103,13 @@ LL -     #[coverage = "off"]
 LL +     #[coverage(on)]
    |
 
-error: malformed `coverage` attribute input
-  --> $DIR/name-value.rs:44:5
+error[E0539]: malformed `coverage` attribute input
+  --> $DIR/name-value.rs:40:5
    |
 LL |     #[coverage = "off"]
-   |     ^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL -     #[coverage = "off"]
 LL +     #[coverage(off)]
@@ -118,13 +118,13 @@ LL -     #[coverage = "off"]
 LL +     #[coverage(on)]
    |
 
-error: malformed `coverage` attribute input
-  --> $DIR/name-value.rs:50:1
+error[E0539]: malformed `coverage` attribute input
+  --> $DIR/name-value.rs:45:1
    |
 LL | #[coverage = "off"]
-   | ^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL - #[coverage = "off"]
 LL + #[coverage(off)]
@@ -133,13 +133,13 @@ LL - #[coverage = "off"]
 LL + #[coverage(on)]
    |
 
-error: malformed `coverage` attribute input
-  --> $DIR/name-value.rs:53:5
+error[E0539]: malformed `coverage` attribute input
+  --> $DIR/name-value.rs:48:5
    |
 LL |     #[coverage = "off"]
-   |     ^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL -     #[coverage = "off"]
 LL +     #[coverage(off)]
@@ -148,13 +148,13 @@ LL -     #[coverage = "off"]
 LL +     #[coverage(on)]
    |
 
-error: malformed `coverage` attribute input
-  --> $DIR/name-value.rs:58:5
+error[E0539]: malformed `coverage` attribute input
+  --> $DIR/name-value.rs:52:5
    |
 LL |     #[coverage = "off"]
-   |     ^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL -     #[coverage = "off"]
 LL +     #[coverage(off)]
@@ -163,13 +163,13 @@ LL -     #[coverage = "off"]
 LL +     #[coverage(on)]
    |
 
-error: malformed `coverage` attribute input
-  --> $DIR/name-value.rs:64:1
+error[E0539]: malformed `coverage` attribute input
+  --> $DIR/name-value.rs:57:1
    |
 LL | #[coverage = "off"]
-   | ^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL - #[coverage = "off"]
 LL + #[coverage(off)]
@@ -178,87 +178,6 @@ LL - #[coverage = "off"]
 LL + #[coverage(on)]
    |
 
-error[E0788]: coverage attribute not allowed here
-  --> $DIR/name-value.rs:21:1
-   |
-LL | #[coverage = "off"]
-   | ^^^^^^^^^^^^^^^^^^^
-...
-LL | struct MyStruct;
-   | ---------------- not a function, impl block, or module
-   |
-   = help: coverage attribute can be applied to a function (with body), impl block, or module
-
-error[E0788]: coverage attribute not allowed here
-  --> $DIR/name-value.rs:35:1
-   |
-LL |   #[coverage = "off"]
-   |   ^^^^^^^^^^^^^^^^^^^
-...
-LL | / trait MyTrait {
-LL | |     #[coverage = "off"]
-...  |
-LL | |     type T;
-LL | | }
-   | |_- not a function, impl block, or module
-   |
-   = help: coverage attribute can be applied to a function (with body), impl block, or module
-
-error[E0788]: coverage attribute not allowed here
-  --> $DIR/name-value.rs:39:5
-   |
-LL |     #[coverage = "off"]
-   |     ^^^^^^^^^^^^^^^^^^^
-...
-LL |     const X: u32;
-   |     ------------- not a function, impl block, or module
-   |
-   = help: coverage attribute can be applied to a function (with body), impl block, or module
-
-error[E0788]: coverage attribute not allowed here
-  --> $DIR/name-value.rs:44:5
-   |
-LL |     #[coverage = "off"]
-   |     ^^^^^^^^^^^^^^^^^^^
-...
-LL |     type T;
-   |     ------- not a function, impl block, or module
-   |
-   = help: coverage attribute can be applied to a function (with body), impl block, or module
-
-error[E0788]: coverage attribute not allowed here
-  --> $DIR/name-value.rs:29:5
-   |
-LL |     #[coverage = "off"]
-   |     ^^^^^^^^^^^^^^^^^^^
-...
-LL |     const X: u32 = 7;
-   |     ----------------- not a function, impl block, or module
-   |
-   = help: coverage attribute can be applied to a function (with body), impl block, or module
-
-error[E0788]: coverage attribute not allowed here
-  --> $DIR/name-value.rs:53:5
-   |
-LL |     #[coverage = "off"]
-   |     ^^^^^^^^^^^^^^^^^^^
-...
-LL |     const X: u32 = 8;
-   |     ----------------- not a function, impl block, or module
-   |
-   = help: coverage attribute can be applied to a function (with body), impl block, or module
-
-error[E0788]: coverage attribute not allowed here
-  --> $DIR/name-value.rs:58:5
-   |
-LL |     #[coverage = "off"]
-   |     ^^^^^^^^^^^^^^^^^^^
-...
-LL |     type T = ();
-   |     ------------ not a function, impl block, or module
-   |
-   = help: coverage attribute can be applied to a function (with body), impl block, or module
-
-error: aborting due to 19 previous errors
+error: aborting due to 12 previous errors
 
-For more information about this error, try `rustc --explain E0788`.
+For more information about this error, try `rustc --explain E0539`.
diff --git a/tests/ui/coverage-attr/subword.stderr b/tests/ui/coverage-attr/subword.stderr
index a5d1a492181..32a09a10c84 100644
--- a/tests/ui/coverage-attr/subword.stderr
+++ b/tests/ui/coverage-attr/subword.stderr
@@ -1,10 +1,12 @@
-error: malformed `coverage` attribute input
+error[E0539]: malformed `coverage` attribute input
   --> $DIR/subword.rs:8:1
    |
 LL | #[coverage(yes(milord))]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^-----------^^
+   |            |
+   |            valid arguments are `on` or `off`
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL - #[coverage(yes(milord))]
 LL + #[coverage(off)]
@@ -13,13 +15,15 @@ LL - #[coverage(yes(milord))]
 LL + #[coverage(on)]
    |
 
-error: malformed `coverage` attribute input
+error[E0539]: malformed `coverage` attribute input
   --> $DIR/subword.rs:11:1
    |
 LL | #[coverage(no(milord))]
-   | ^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^----------^^
+   |            |
+   |            valid arguments are `on` or `off`
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL - #[coverage(no(milord))]
 LL + #[coverage(off)]
@@ -28,13 +32,15 @@ LL - #[coverage(no(milord))]
 LL + #[coverage(on)]
    |
 
-error: malformed `coverage` attribute input
+error[E0539]: malformed `coverage` attribute input
   --> $DIR/subword.rs:14:1
    |
 LL | #[coverage(yes = "milord")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^--------------^^
+   |            |
+   |            valid arguments are `on` or `off`
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL - #[coverage(yes = "milord")]
 LL + #[coverage(off)]
@@ -43,13 +49,15 @@ LL - #[coverage(yes = "milord")]
 LL + #[coverage(on)]
    |
 
-error: malformed `coverage` attribute input
+error[E0539]: malformed `coverage` attribute input
   --> $DIR/subword.rs:17:1
    |
 LL | #[coverage(no = "milord")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^-------------^^
+   |            |
+   |            valid arguments are `on` or `off`
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL - #[coverage(no = "milord")]
 LL + #[coverage(off)]
@@ -60,3 +68,4 @@ LL + #[coverage(on)]
 
 error: aborting due to 4 previous errors
 
+For more information about this error, try `rustc --explain E0539`.
diff --git a/tests/ui/coverage-attr/word-only.rs b/tests/ui/coverage-attr/word-only.rs
index d0f743938f3..81bd558b8b0 100644
--- a/tests/ui/coverage-attr/word-only.rs
+++ b/tests/ui/coverage-attr/word-only.rs
@@ -20,7 +20,6 @@ mod my_mod_inner {
 
 #[coverage]
 //~^ ERROR malformed `coverage` attribute input
-//~| ERROR [E0788]
 struct MyStruct;
 
 #[coverage]
@@ -28,22 +27,18 @@ struct MyStruct;
 impl MyStruct {
     #[coverage]
     //~^ ERROR malformed `coverage` attribute input
-    //~| ERROR [E0788]
     const X: u32 = 7;
 }
 
 #[coverage]
 //~^ ERROR malformed `coverage` attribute input
-//~| ERROR [E0788]
 trait MyTrait {
     #[coverage]
     //~^ ERROR malformed `coverage` attribute input
-    //~| ERROR [E0788]
     const X: u32;
 
     #[coverage]
     //~^ ERROR malformed `coverage` attribute input
-    //~| ERROR [E0788]
     type T;
 }
 
@@ -52,12 +47,10 @@ trait MyTrait {
 impl MyTrait for MyStruct {
     #[coverage]
     //~^ ERROR malformed `coverage` attribute input
-    //~| ERROR [E0788]
     const X: u32 = 8;
 
     #[coverage]
     //~^ ERROR malformed `coverage` attribute input
-    //~| ERROR [E0788]
     type T = ();
 }
 
diff --git a/tests/ui/coverage-attr/word-only.stderr b/tests/ui/coverage-attr/word-only.stderr
index 2773db9c857..dd161360a5c 100644
--- a/tests/ui/coverage-attr/word-only.stderr
+++ b/tests/ui/coverage-attr/word-only.stderr
@@ -1,240 +1,161 @@
-error: malformed `coverage` attribute input
+error[E0539]: malformed `coverage` attribute input
   --> $DIR/word-only.rs:12:1
    |
 LL | #[coverage]
-   | ^^^^^^^^^^^
+   | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL | #[coverage(off)]
    |           +++++
 LL | #[coverage(on)]
    |           ++++
 
-error: malformed `coverage` attribute input
+error[E0539]: malformed `coverage` attribute input
   --> $DIR/word-only.rs:17:5
    |
 LL |     #![coverage]
-   |     ^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL -     #![coverage]
+LL +     #[coverage(off)]
+   |
+LL -     #![coverage]
+LL +     #[coverage(on)]
    |
-LL |     #![coverage(off)]
-   |                +++++
-LL |     #![coverage(on)]
-   |                ++++
 
-error: malformed `coverage` attribute input
+error[E0539]: malformed `coverage` attribute input
   --> $DIR/word-only.rs:21:1
    |
 LL | #[coverage]
-   | ^^^^^^^^^^^
+   | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL | #[coverage(off)]
    |           +++++
 LL | #[coverage(on)]
    |           ++++
 
-error: malformed `coverage` attribute input
-  --> $DIR/word-only.rs:26:1
+error[E0539]: malformed `coverage` attribute input
+  --> $DIR/word-only.rs:25:1
    |
 LL | #[coverage]
-   | ^^^^^^^^^^^
+   | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL | #[coverage(off)]
    |           +++++
 LL | #[coverage(on)]
    |           ++++
 
-error: malformed `coverage` attribute input
-  --> $DIR/word-only.rs:29:5
+error[E0539]: malformed `coverage` attribute input
+  --> $DIR/word-only.rs:28:5
    |
 LL |     #[coverage]
-   |     ^^^^^^^^^^^
+   |     ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL |     #[coverage(off)]
    |               +++++
 LL |     #[coverage(on)]
    |               ++++
 
-error: malformed `coverage` attribute input
-  --> $DIR/word-only.rs:35:1
+error[E0539]: malformed `coverage` attribute input
+  --> $DIR/word-only.rs:33:1
    |
 LL | #[coverage]
-   | ^^^^^^^^^^^
+   | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL | #[coverage(off)]
    |           +++++
 LL | #[coverage(on)]
    |           ++++
 
-error: malformed `coverage` attribute input
-  --> $DIR/word-only.rs:39:5
+error[E0539]: malformed `coverage` attribute input
+  --> $DIR/word-only.rs:36:5
    |
 LL |     #[coverage]
-   |     ^^^^^^^^^^^
+   |     ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL |     #[coverage(off)]
    |               +++++
 LL |     #[coverage(on)]
    |               ++++
 
-error: malformed `coverage` attribute input
-  --> $DIR/word-only.rs:44:5
+error[E0539]: malformed `coverage` attribute input
+  --> $DIR/word-only.rs:40:5
    |
 LL |     #[coverage]
-   |     ^^^^^^^^^^^
+   |     ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL |     #[coverage(off)]
    |               +++++
 LL |     #[coverage(on)]
    |               ++++
 
-error: malformed `coverage` attribute input
-  --> $DIR/word-only.rs:50:1
+error[E0539]: malformed `coverage` attribute input
+  --> $DIR/word-only.rs:45:1
    |
 LL | #[coverage]
-   | ^^^^^^^^^^^
+   | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL | #[coverage(off)]
    |           +++++
 LL | #[coverage(on)]
    |           ++++
 
-error: malformed `coverage` attribute input
-  --> $DIR/word-only.rs:53:5
+error[E0539]: malformed `coverage` attribute input
+  --> $DIR/word-only.rs:48:5
    |
 LL |     #[coverage]
-   |     ^^^^^^^^^^^
+   |     ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL |     #[coverage(off)]
    |               +++++
 LL |     #[coverage(on)]
    |               ++++
 
-error: malformed `coverage` attribute input
-  --> $DIR/word-only.rs:58:5
+error[E0539]: malformed `coverage` attribute input
+  --> $DIR/word-only.rs:52:5
    |
 LL |     #[coverage]
-   |     ^^^^^^^^^^^
+   |     ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL |     #[coverage(off)]
    |               +++++
 LL |     #[coverage(on)]
    |               ++++
 
-error: malformed `coverage` attribute input
-  --> $DIR/word-only.rs:64:1
+error[E0539]: malformed `coverage` attribute input
+  --> $DIR/word-only.rs:57:1
    |
 LL | #[coverage]
-   | ^^^^^^^^^^^
+   | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
 LL | #[coverage(off)]
    |           +++++
 LL | #[coverage(on)]
    |           ++++
 
-error[E0788]: coverage attribute not allowed here
-  --> $DIR/word-only.rs:21:1
-   |
-LL | #[coverage]
-   | ^^^^^^^^^^^
-...
-LL | struct MyStruct;
-   | ---------------- not a function, impl block, or module
-   |
-   = help: coverage attribute can be applied to a function (with body), impl block, or module
-
-error[E0788]: coverage attribute not allowed here
-  --> $DIR/word-only.rs:35:1
-   |
-LL |   #[coverage]
-   |   ^^^^^^^^^^^
-...
-LL | / trait MyTrait {
-LL | |     #[coverage]
-...  |
-LL | |     type T;
-LL | | }
-   | |_- not a function, impl block, or module
-   |
-   = help: coverage attribute can be applied to a function (with body), impl block, or module
-
-error[E0788]: coverage attribute not allowed here
-  --> $DIR/word-only.rs:39:5
-   |
-LL |     #[coverage]
-   |     ^^^^^^^^^^^
-...
-LL |     const X: u32;
-   |     ------------- not a function, impl block, or module
-   |
-   = help: coverage attribute can be applied to a function (with body), impl block, or module
-
-error[E0788]: coverage attribute not allowed here
-  --> $DIR/word-only.rs:44:5
-   |
-LL |     #[coverage]
-   |     ^^^^^^^^^^^
-...
-LL |     type T;
-   |     ------- not a function, impl block, or module
-   |
-   = help: coverage attribute can be applied to a function (with body), impl block, or module
-
-error[E0788]: coverage attribute not allowed here
-  --> $DIR/word-only.rs:29:5
-   |
-LL |     #[coverage]
-   |     ^^^^^^^^^^^
-...
-LL |     const X: u32 = 7;
-   |     ----------------- not a function, impl block, or module
-   |
-   = help: coverage attribute can be applied to a function (with body), impl block, or module
-
-error[E0788]: coverage attribute not allowed here
-  --> $DIR/word-only.rs:53:5
-   |
-LL |     #[coverage]
-   |     ^^^^^^^^^^^
-...
-LL |     const X: u32 = 8;
-   |     ----------------- not a function, impl block, or module
-   |
-   = help: coverage attribute can be applied to a function (with body), impl block, or module
-
-error[E0788]: coverage attribute not allowed here
-  --> $DIR/word-only.rs:58:5
-   |
-LL |     #[coverage]
-   |     ^^^^^^^^^^^
-...
-LL |     type T = ();
-   |     ------------ not a function, impl block, or module
-   |
-   = help: coverage attribute can be applied to a function (with body), impl block, or module
-
-error: aborting due to 19 previous errors
+error: aborting due to 12 previous errors
 
-For more information about this error, try `rustc --explain E0788`.
+For more information about this error, try `rustc --explain E0539`.