From d4005b68119701c36a7930320b51d3666750020a Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 24 Dec 2024 22:59:11 +1100 Subject: [PATCH 1/6] Rename `tests/ui/coverage-attr/no-coverage.rs` to `allowed-positions.rs` --- .../{no-coverage.rs => allowed-positions.rs} | 4 ++- ...verage.stderr => allowed-positions.stderr} | 26 +++++++++---------- 2 files changed, 16 insertions(+), 14 deletions(-) rename tests/ui/coverage-attr/{no-coverage.rs => allowed-positions.rs} (96%) rename tests/ui/coverage-attr/{no-coverage.stderr => allowed-positions.stderr} (85%) diff --git a/tests/ui/coverage-attr/no-coverage.rs b/tests/ui/coverage-attr/allowed-positions.rs similarity index 96% rename from tests/ui/coverage-attr/no-coverage.rs rename to tests/ui/coverage-attr/allowed-positions.rs index c386f25816e4c..bfffbd2625027 100644 --- a/tests/ui/coverage-attr/no-coverage.rs +++ b/tests/ui/coverage-attr/allowed-positions.rs @@ -1,7 +1,9 @@ +//! Tests where the `#[coverage(..)]` attribute can and cannot be used. + //@ reference: attributes.coverage.allowed-positions -#![feature(extern_types)] #![feature(coverage_attribute)] +#![feature(extern_types)] #![feature(impl_trait_in_assoc_type)] #![warn(unused_attributes)] #![coverage(off)] diff --git a/tests/ui/coverage-attr/no-coverage.stderr b/tests/ui/coverage-attr/allowed-positions.stderr similarity index 85% rename from tests/ui/coverage-attr/no-coverage.stderr rename to tests/ui/coverage-attr/allowed-positions.stderr index f5a44ecec747f..80099fbd6dd7e 100644 --- a/tests/ui/coverage-attr/no-coverage.stderr +++ b/tests/ui/coverage-attr/allowed-positions.stderr @@ -1,5 +1,5 @@ error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/no-coverage.rs:9:1 + --> $DIR/allowed-positions.rs:11:1 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ @@ -12,7 +12,7 @@ LL | | } | |_- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/no-coverage.rs:50:5 + --> $DIR/allowed-positions.rs:52:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ @@ -20,7 +20,7 @@ LL | let _ = (); | ----------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/no-coverage.rs:54:9 + --> $DIR/allowed-positions.rs:56:9 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ @@ -28,7 +28,7 @@ LL | () => (), | -------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/no-coverage.rs:58:5 + --> $DIR/allowed-positions.rs:60:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ @@ -36,7 +36,7 @@ LL | return (); | --------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/no-coverage.rs:11:5 + --> $DIR/allowed-positions.rs:13:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ @@ -44,7 +44,7 @@ LL | const X: u32; | ------------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/no-coverage.rs:14:5 + --> $DIR/allowed-positions.rs:16:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ @@ -52,7 +52,7 @@ LL | type T; | ------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/no-coverage.rs:19:5 + --> $DIR/allowed-positions.rs:21:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ @@ -60,7 +60,7 @@ LL | fn f(&self); | ------------ not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/no-coverage.rs:22:5 + --> $DIR/allowed-positions.rs:24:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ @@ -68,7 +68,7 @@ LL | fn g(); | ------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/no-coverage.rs:30:5 + --> $DIR/allowed-positions.rs:32:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ @@ -76,7 +76,7 @@ LL | type T = Self; | -------------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/no-coverage.rs:33:5 + --> $DIR/allowed-positions.rs:35:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ @@ -84,7 +84,7 @@ LL | type U = impl Trait; | -------------------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/no-coverage.rs:41:5 + --> $DIR/allowed-positions.rs:43:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ @@ -92,7 +92,7 @@ LL | static X: u32; | -------------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/no-coverage.rs:44:5 + --> $DIR/allowed-positions.rs:46:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ @@ -100,7 +100,7 @@ LL | type T; | ------- not a function or closure error: unconstrained opaque type - --> $DIR/no-coverage.rs:34:14 + --> $DIR/allowed-positions.rs:36:14 | LL | type U = impl Trait; | ^^^^^^^^^^ From 5e98118901e9d358cc246e3fabe119bcd6a245bc Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 24 Dec 2024 23:08:28 +1100 Subject: [PATCH 2/6] Fully redact the [E0788] error message in tests, to make changes easier --- tests/ui/coverage-attr/allowed-positions.rs | 24 ++++++++++----------- tests/ui/coverage-attr/name-value.rs | 14 ++++++------ tests/ui/coverage-attr/word-only.rs | 14 ++++++------ 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/tests/ui/coverage-attr/allowed-positions.rs b/tests/ui/coverage-attr/allowed-positions.rs index bfffbd2625027..3c400761948a2 100644 --- a/tests/ui/coverage-attr/allowed-positions.rs +++ b/tests/ui/coverage-attr/allowed-positions.rs @@ -8,20 +8,20 @@ #![warn(unused_attributes)] #![coverage(off)] -#[coverage(off)] //~ ERROR attribute should be applied to a function definition or closure +#[coverage(off)] //~ ERROR [E0788] trait Trait { - #[coverage(off)] //~ ERROR attribute should be applied to a function definition or closure + #[coverage(off)] //~ ERROR [E0788] const X: u32; - #[coverage(off)] //~ ERROR attribute should be applied to a function definition or closure + #[coverage(off)] //~ ERROR [E0788] type T; type U; - #[coverage(off)] //~ ERROR attribute should be applied to a function definition or closure + #[coverage(off)] //~ ERROR [E0788] fn f(&self); - #[coverage(off)] //~ ERROR attribute should be applied to a function definition or closure + #[coverage(off)] //~ ERROR [E0788] fn g(); } @@ -29,10 +29,10 @@ trait Trait { impl Trait for () { const X: u32 = 0; - #[coverage(off)] //~ ERROR attribute should be applied to a function definition or closure + #[coverage(off)] //~ ERROR [E0788] type T = Self; - #[coverage(off)] //~ ERROR attribute should be applied to a function definition or closure + #[coverage(off)] //~ ERROR [E0788] type U = impl Trait; //~ ERROR unconstrained opaque type fn f(&self) {} @@ -40,23 +40,23 @@ impl Trait for () { } extern "C" { - #[coverage(off)] //~ ERROR attribute should be applied to a function definition or closure + #[coverage(off)] //~ ERROR [E0788] static X: u32; - #[coverage(off)] //~ ERROR attribute should be applied to a function definition or closure + #[coverage(off)] //~ ERROR [E0788] type T; } #[coverage(off)] fn main() { - #[coverage(off)] //~ ERROR attribute should be applied to a function definition or closure + #[coverage(off)] //~ ERROR [E0788] let _ = (); match () { - #[coverage(off)] //~ ERROR attribute should be applied to a function definition or closure + #[coverage(off)] //~ ERROR [E0788] () => (), } - #[coverage(off)] //~ ERROR attribute should be applied to a function definition or closure + #[coverage(off)] //~ ERROR [E0788] return (); } diff --git a/tests/ui/coverage-attr/name-value.rs b/tests/ui/coverage-attr/name-value.rs index e5df5bc3da0a7..ffd9afe2ce186 100644 --- a/tests/ui/coverage-attr/name-value.rs +++ b/tests/ui/coverage-attr/name-value.rs @@ -20,7 +20,7 @@ mod my_mod_inner { #[coverage = "off"] //~^ ERROR malformed `coverage` attribute input -//~| ERROR attribute should be applied to a function definition or closure +//~| ERROR [E0788] struct MyStruct; #[coverage = "off"] @@ -28,22 +28,22 @@ struct MyStruct; impl MyStruct { #[coverage = "off"] //~^ ERROR malformed `coverage` attribute input - //~| ERROR attribute should be applied to a function definition or closure + //~| ERROR [E0788] const X: u32 = 7; } #[coverage = "off"] //~^ ERROR malformed `coverage` attribute input -//~| ERROR attribute should be applied to a function definition or closure +//~| ERROR [E0788] trait MyTrait { #[coverage = "off"] //~^ ERROR malformed `coverage` attribute input - //~| ERROR attribute should be applied to a function definition or closure + //~| ERROR [E0788] const X: u32; #[coverage = "off"] //~^ ERROR malformed `coverage` attribute input - //~| ERROR attribute should be applied to a function definition or closure + //~| ERROR [E0788] type T; } @@ -52,12 +52,12 @@ trait MyTrait { impl MyTrait for MyStruct { #[coverage = "off"] //~^ ERROR malformed `coverage` attribute input - //~| ERROR attribute should be applied to a function definition or closure + //~| ERROR [E0788] const X: u32 = 8; #[coverage = "off"] //~^ ERROR malformed `coverage` attribute input - //~| ERROR attribute should be applied to a function definition or closure + //~| ERROR [E0788] type T = (); } diff --git a/tests/ui/coverage-attr/word-only.rs b/tests/ui/coverage-attr/word-only.rs index add225cdb9363..d0f743938f3af 100644 --- a/tests/ui/coverage-attr/word-only.rs +++ b/tests/ui/coverage-attr/word-only.rs @@ -20,7 +20,7 @@ mod my_mod_inner { #[coverage] //~^ ERROR malformed `coverage` attribute input -//~| ERROR attribute should be applied to a function definition or closure +//~| ERROR [E0788] struct MyStruct; #[coverage] @@ -28,22 +28,22 @@ struct MyStruct; impl MyStruct { #[coverage] //~^ ERROR malformed `coverage` attribute input - //~| ERROR attribute should be applied to a function definition or closure + //~| ERROR [E0788] const X: u32 = 7; } #[coverage] //~^ ERROR malformed `coverage` attribute input -//~| ERROR attribute should be applied to a function definition or closure +//~| ERROR [E0788] trait MyTrait { #[coverage] //~^ ERROR malformed `coverage` attribute input - //~| ERROR attribute should be applied to a function definition or closure + //~| ERROR [E0788] const X: u32; #[coverage] //~^ ERROR malformed `coverage` attribute input - //~| ERROR attribute should be applied to a function definition or closure + //~| ERROR [E0788] type T; } @@ -52,12 +52,12 @@ trait MyTrait { impl MyTrait for MyStruct { #[coverage] //~^ ERROR malformed `coverage` attribute input - //~| ERROR attribute should be applied to a function definition or closure + //~| ERROR [E0788] const X: u32 = 8; #[coverage] //~^ ERROR malformed `coverage` attribute input - //~| ERROR attribute should be applied to a function definition or closure + //~| ERROR [E0788] type T = (); } From 9124662da3e0d573703c9bb07d5e3cf8d06f1b20 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 25 Dec 2024 13:29:20 +1100 Subject: [PATCH 3/6] Expand the main test for where the coverage attribute is allowed Some of these cases are also implicitly checked by other tests, but it's helpful to also explicitly list them in the main test. --- tests/ui/coverage-attr/allowed-positions.rs | 80 ++++++++++-- .../ui/coverage-attr/allowed-positions.stderr | 116 ++++++++++++------ 2 files changed, 148 insertions(+), 48 deletions(-) diff --git a/tests/ui/coverage-attr/allowed-positions.rs b/tests/ui/coverage-attr/allowed-positions.rs index 3c400761948a2..d4345c8d4432b 100644 --- a/tests/ui/coverage-attr/allowed-positions.rs +++ b/tests/ui/coverage-attr/allowed-positions.rs @@ -8,35 +8,68 @@ #![warn(unused_attributes)] #![coverage(off)] +#[coverage(off)] +mod submod {} + #[coverage(off)] //~ ERROR [E0788] -trait Trait { - #[coverage(off)] //~ ERROR [E0788] - const X: u32; +type MyTypeAlias = (); +#[coverage(off)] //~ ERROR [E0788] +trait MyTrait { #[coverage(off)] //~ ERROR [E0788] - type T; + const TRAIT_ASSOC_CONST: u32; - type U; + #[coverage(off)] //~ ERROR [E0788] + type TraitAssocType; #[coverage(off)] //~ ERROR [E0788] - fn f(&self); + fn trait_method(&self); + + #[coverage(off)] + fn trait_method_with_default(&self) {} #[coverage(off)] //~ ERROR [E0788] - fn g(); + fn trait_assoc_fn(); } #[coverage(off)] -impl Trait for () { - const X: u32 = 0; +impl MyTrait for () { + const TRAIT_ASSOC_CONST: u32 = 0; #[coverage(off)] //~ ERROR [E0788] - type T = Self; + type TraitAssocType = Self; + + #[coverage(off)] + fn trait_method(&self) {} + #[coverage(off)] + fn trait_method_with_default(&self) {} + #[coverage(off)] + fn trait_assoc_fn() {} +} + +trait HasAssocType { + type T; + fn constrain_assoc_type() -> Self::T; +} +impl HasAssocType for () { #[coverage(off)] //~ ERROR [E0788] - type U = impl Trait; //~ ERROR unconstrained opaque type + type T = impl Copy; + fn constrain_assoc_type() -> Self::T {} +} + +#[coverage(off)] //~ ERROR [E0788] +struct MyStruct { + #[coverage(off)] //~ ERROR [E0788] + field: u32, +} - fn f(&self) {} - fn g() {} +#[coverage(off)] +impl MyStruct { + #[coverage(off)] + fn method(&self) {} + #[coverage(off)] + fn assoc_fn() {} } extern "C" { @@ -45,6 +78,9 @@ extern "C" { #[coverage(off)] //~ ERROR [E0788] type T; + + #[coverage(off)] //~ ERROR [E0788] + fn foreign_fn(); } #[coverage(off)] @@ -52,6 +88,24 @@ fn main() { #[coverage(off)] //~ ERROR [E0788] let _ = (); + // Currently not allowed on let statements, even if they bind to a closure. + // It might be nice to support this as a special case someday, but trying + // to define the precise boundaries of that special case might be tricky. + #[coverage(off)] //~ ERROR [E0788] + let _let_closure = || (); + + // In situations where attributes can already be applied to expressions, + // the coverage attribute is allowed on closure expressions. + let _closure_tail_expr = { + #[coverage(off)] + || () + }; + + // Applying attributes to arbitrary expressions requires an unstable + // feature, but if that feature were enabled then this would be allowed. + let _closure_expr = #[coverage(off)] || (); + //~^ ERROR attributes on expressions are experimental [E0658] + match () { #[coverage(off)] //~ ERROR [E0788] () => (), diff --git a/tests/ui/coverage-attr/allowed-positions.stderr b/tests/ui/coverage-attr/allowed-positions.stderr index 80099fbd6dd7e..08a578ddd834d 100644 --- a/tests/ui/coverage-attr/allowed-positions.stderr +++ b/tests/ui/coverage-attr/allowed-positions.stderr @@ -1,18 +1,55 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/allowed-positions.rs:106:25 + | +LL | let _closure_expr = #[coverage(off)] || (); + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` 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[E0788]: attribute should be applied to a function definition or closure - --> $DIR/allowed-positions.rs:11:1 + --> $DIR/allowed-positions.rs:14:1 + | +LL | #[coverage(off)] + | ^^^^^^^^^^^^^^^^ +LL | type MyTypeAlias = (); + | ---------------------- not a function or closure + +error[E0788]: attribute should be applied to a function definition or closure + --> $DIR/allowed-positions.rs:17:1 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ -LL | / trait Trait { +LL | / trait MyTrait { LL | | #[coverage(off)] -LL | | const X: u32; +LL | | const TRAIT_ASSOC_CONST: u32; ... | -LL | | fn g(); +LL | | fn trait_assoc_fn(); +LL | | } + | |_- not a function or closure + +error[E0788]: attribute should be applied to a function definition or closure + --> $DIR/allowed-positions.rs:61:1 + | +LL | #[coverage(off)] + | ^^^^^^^^^^^^^^^^ +LL | / struct MyStruct { +LL | | #[coverage(off)] +LL | | field: u32, LL | | } | |_- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/allowed-positions.rs:52:5 + --> $DIR/allowed-positions.rs:63:5 + | +LL | #[coverage(off)] + | ^^^^^^^^^^^^^^^^ +LL | field: u32, + | ---------- not a function or closure + +error[E0788]: attribute should be applied to a function definition or closure + --> $DIR/allowed-positions.rs:88:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ @@ -20,7 +57,15 @@ LL | let _ = (); | ----------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/allowed-positions.rs:56:9 + --> $DIR/allowed-positions.rs:94:5 + | +LL | #[coverage(off)] + | ^^^^^^^^^^^^^^^^ +LL | let _let_closure = || (); + | ------------------------- not a function or closure + +error[E0788]: attribute should be applied to a function definition or closure + --> $DIR/allowed-positions.rs:110:9 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ @@ -28,7 +73,7 @@ LL | () => (), | -------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/allowed-positions.rs:60:5 + --> $DIR/allowed-positions.rs:114:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ @@ -36,55 +81,55 @@ LL | return (); | --------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/allowed-positions.rs:13:5 + --> $DIR/allowed-positions.rs:19:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ -LL | const X: u32; - | ------------- not a function or closure +LL | const TRAIT_ASSOC_CONST: u32; + | ----------------------------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/allowed-positions.rs:16:5 + --> $DIR/allowed-positions.rs:22:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ -LL | type T; - | ------- not a function or closure +LL | type TraitAssocType; + | -------------------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/allowed-positions.rs:21:5 + --> $DIR/allowed-positions.rs:25:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ -LL | fn f(&self); - | ------------ not a function or closure +LL | fn trait_method(&self); + | ----------------------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/allowed-positions.rs:24:5 + --> $DIR/allowed-positions.rs:31:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ -LL | fn g(); - | ------- not a function or closure +LL | fn trait_assoc_fn(); + | -------------------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/allowed-positions.rs:32:5 + --> $DIR/allowed-positions.rs:39:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ -LL | type T = Self; - | -------------- not a function or closure +LL | type TraitAssocType = Self; + | --------------------------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/allowed-positions.rs:35:5 + --> $DIR/allowed-positions.rs:56:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ -LL | type U = impl Trait; - | -------------------- not a function or closure +LL | type T = impl Copy; + | ------------------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/allowed-positions.rs:43:5 + --> $DIR/allowed-positions.rs:76:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ @@ -92,21 +137,22 @@ LL | static X: u32; | -------------- not a function or closure error[E0788]: attribute should be applied to a function definition or closure - --> $DIR/allowed-positions.rs:46:5 + --> $DIR/allowed-positions.rs:79:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ LL | type T; | ------- not a function or closure -error: unconstrained opaque type - --> $DIR/allowed-positions.rs:36:14 - | -LL | type U = impl Trait; - | ^^^^^^^^^^ +error[E0788]: attribute should be applied to a function definition or closure + --> $DIR/allowed-positions.rs:82:5 | - = note: `U` must be used in combination with a concrete type within the same impl +LL | #[coverage(off)] + | ^^^^^^^^^^^^^^^^ +LL | fn foreign_fn(); + | ---------------- not a function or closure -error: aborting due to 13 previous errors +error: aborting due to 18 previous errors -For more information about this error, try `rustc --explain E0788`. +Some errors have detailed explanations: E0658, E0788. +For more information about an error, try `rustc --explain E0658`. From 399620939844d7b2e4a93e450f8c578960d0b6f2 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 25 Dec 2024 14:57:21 +1100 Subject: [PATCH 4/6] Overhaul error messages for disallowed coverage attributes --- compiler/rustc_passes/messages.ftl | 8 +- compiler/rustc_passes/src/check_attr.rs | 25 +++-- compiler/rustc_passes/src/errors.rs | 16 ++- .../ui/coverage-attr/allowed-positions.stderr | 102 ++++++++++++------ tests/ui/coverage-attr/name-value.stderr | 42 +++++--- tests/ui/coverage-attr/word-only.stderr | 42 +++++--- 6 files changed, 160 insertions(+), 75 deletions(-) diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index ba3101e9058aa..f39bea2a56fcc 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -112,9 +112,11 @@ passes_coroutine_on_non_closure = attribute should be applied to closures .label = not a closure -passes_coverage_not_fn_or_closure = - attribute should be applied to a function definition or closure - .label = not a function or closure +passes_coverage_attribute_not_allowed = + coverage attribute not allowed here + .not_fn_impl_mod = not a function, impl block, or module + .no_body = function has no body + .help = coverage attribute can be applied to a function (with body), impl block, or module passes_dead_codes = { $multiple -> diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 8cf20a378d4e4..12f715a0fe4a4 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 163325f2a3c6f..d95fa5db0ceee 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, + /// "function has no body" + #[label(passes_no_body)] + pub no_body: Option, + /// "coverage attribute can be applied to a function (with body), impl block, or module" + #[help] + pub help: (), } #[derive(Diagnostic)] diff --git a/tests/ui/coverage-attr/allowed-positions.stderr b/tests/ui/coverage-attr/allowed-positions.stderr index 08a578ddd834d..34562a4da1b8a 100644 --- a/tests/ui/coverage-attr/allowed-positions.stderr +++ b/tests/ui/coverage-attr/allowed-positions.stderr @@ -8,15 +8,17 @@ LL | let _closure_expr = #[coverage(off)] || (); = help: add `#![feature(stmt_expr_attributes)]` 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[E0788]: attribute should be applied to a function definition or closure +error[E0788]: coverage attribute not allowed here --> $DIR/allowed-positions.rs:14:1 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ LL | type MyTypeAlias = (); - | ---------------------- not a function or closure + | ---------------------- not a function, impl block, or module + | + = help: coverage attribute can be applied to a function (with body), impl block, or module -error[E0788]: attribute should be applied to a function definition or closure +error[E0788]: coverage attribute not allowed here --> $DIR/allowed-positions.rs:17:1 | LL | #[coverage(off)] @@ -27,9 +29,11 @@ LL | | const TRAIT_ASSOC_CONST: u32; ... | LL | | fn trait_assoc_fn(); LL | | } - | |_- not a function or closure + | |_- not a function, impl block, or module + | + = help: coverage attribute can be applied to a function (with body), impl block, or module -error[E0788]: attribute should be applied to a function definition or closure +error[E0788]: coverage attribute not allowed here --> $DIR/allowed-positions.rs:61:1 | LL | #[coverage(off)] @@ -38,119 +42,149 @@ LL | / struct MyStruct { LL | | #[coverage(off)] LL | | field: u32, LL | | } - | |_- not a function or closure + | |_- not a function, impl block, or module + | + = help: coverage attribute can be applied to a function (with body), impl block, or module -error[E0788]: attribute should be applied to a function definition or closure +error[E0788]: coverage attribute not allowed here --> $DIR/allowed-positions.rs:63:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ LL | field: u32, - | ---------- not a function or closure + | ---------- not a function, impl block, or module + | + = help: coverage attribute can be applied to a function (with body), impl block, or module -error[E0788]: attribute should be applied to a function definition or closure +error[E0788]: coverage attribute not allowed here --> $DIR/allowed-positions.rs:88:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ LL | let _ = (); - | ----------- not a function or closure + | ----------- not a function, impl block, or module + | + = help: coverage attribute can be applied to a function (with body), impl block, or module -error[E0788]: attribute should be applied to a function definition or closure +error[E0788]: coverage attribute not allowed here --> $DIR/allowed-positions.rs:94:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ LL | let _let_closure = || (); - | ------------------------- not a function or closure + | ------------------------- not a function, impl block, or module + | + = help: coverage attribute can be applied to a function (with body), impl block, or module -error[E0788]: attribute should be applied to a function definition or closure +error[E0788]: coverage attribute not allowed here --> $DIR/allowed-positions.rs:110:9 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ LL | () => (), - | -------- not a function or closure + | -------- not a function, impl block, or module + | + = help: coverage attribute can be applied to a function (with body), impl block, or module -error[E0788]: attribute should be applied to a function definition or closure +error[E0788]: coverage attribute not allowed here --> $DIR/allowed-positions.rs:114:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ LL | return (); - | --------- not a function or closure + | --------- not a function, impl block, or module + | + = help: coverage attribute can be applied to a function (with body), impl block, or module -error[E0788]: attribute should be applied to a function definition or closure +error[E0788]: coverage attribute not allowed here --> $DIR/allowed-positions.rs:19:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ LL | const TRAIT_ASSOC_CONST: u32; - | ----------------------------- not a function or closure + | ----------------------------- not a function, impl block, or module + | + = help: coverage attribute can be applied to a function (with body), impl block, or module -error[E0788]: attribute should be applied to a function definition or closure +error[E0788]: coverage attribute not allowed here --> $DIR/allowed-positions.rs:22:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ LL | type TraitAssocType; - | -------------------- not a function or closure + | -------------------- not a function, impl block, or module + | + = help: coverage attribute can be applied to a function (with body), impl block, or module -error[E0788]: attribute should be applied to a function definition or closure +error[E0788]: coverage attribute not allowed here --> $DIR/allowed-positions.rs:25:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ LL | fn trait_method(&self); - | ----------------------- not a function or closure + | ----------------------- function has no body + | + = help: coverage attribute can be applied to a function (with body), impl block, or module -error[E0788]: attribute should be applied to a function definition or closure +error[E0788]: coverage attribute not allowed here --> $DIR/allowed-positions.rs:31:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ LL | fn trait_assoc_fn(); - | -------------------- not a function or closure + | -------------------- function has no body + | + = help: coverage attribute can be applied to a function (with body), impl block, or module -error[E0788]: attribute should be applied to a function definition or closure +error[E0788]: coverage attribute not allowed here --> $DIR/allowed-positions.rs:39:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ LL | type TraitAssocType = Self; - | --------------------------- not a function or closure + | --------------------------- not a function, impl block, or module + | + = help: coverage attribute can be applied to a function (with body), impl block, or module -error[E0788]: attribute should be applied to a function definition or closure +error[E0788]: coverage attribute not allowed here --> $DIR/allowed-positions.rs:56:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ LL | type T = impl Copy; - | ------------------- not a function or closure + | ------------------- not a function, impl block, or module + | + = help: coverage attribute can be applied to a function (with body), impl block, or module -error[E0788]: attribute should be applied to a function definition or closure +error[E0788]: coverage attribute not allowed here --> $DIR/allowed-positions.rs:76:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ LL | static X: u32; - | -------------- not a function or closure + | -------------- not a function, impl block, or module + | + = help: coverage attribute can be applied to a function (with body), impl block, or module -error[E0788]: attribute should be applied to a function definition or closure +error[E0788]: coverage attribute not allowed here --> $DIR/allowed-positions.rs:79:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ LL | type T; - | ------- not a function or closure + | ------- not a function, impl block, or module + | + = help: coverage attribute can be applied to a function (with body), impl block, or module -error[E0788]: attribute should be applied to a function definition or closure +error[E0788]: coverage attribute not allowed here --> $DIR/allowed-positions.rs:82:5 | LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ LL | fn foreign_fn(); - | ---------------- not a function or closure + | ---------------- function has no body + | + = help: coverage attribute can be applied to a function (with body), impl block, or module error: aborting due to 18 previous errors diff --git a/tests/ui/coverage-attr/name-value.stderr b/tests/ui/coverage-attr/name-value.stderr index 84a57f575f93a..bfd22ed5451bb 100644 --- a/tests/ui/coverage-attr/name-value.stderr +++ b/tests/ui/coverage-attr/name-value.stderr @@ -154,16 +154,18 @@ LL | #[coverage(off)] LL | #[coverage(on)] | -error[E0788]: attribute should be applied to a function definition or closure +error[E0788]: coverage attribute not allowed here --> $DIR/name-value.rs:21:1 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ ... LL | struct MyStruct; - | ---------------- not a function or closure + | ---------------- not a function, impl block, or module + | + = help: coverage attribute can be applied to a function (with body), impl block, or module -error[E0788]: attribute should be applied to a function definition or closure +error[E0788]: coverage attribute not allowed here --> $DIR/name-value.rs:35:1 | LL | #[coverage = "off"] @@ -174,52 +176,64 @@ LL | | #[coverage = "off"] ... | LL | | type T; LL | | } - | |_- not a function or closure + | |_- not a function, impl block, or module + | + = help: coverage attribute can be applied to a function (with body), impl block, or module -error[E0788]: attribute should be applied to a function definition or closure +error[E0788]: coverage attribute not allowed here --> $DIR/name-value.rs:39:5 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ ... LL | const X: u32; - | ------------- not a function or closure + | ------------- not a function, impl block, or module + | + = help: coverage attribute can be applied to a function (with body), impl block, or module -error[E0788]: attribute should be applied to a function definition or closure +error[E0788]: coverage attribute not allowed here --> $DIR/name-value.rs:44:5 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ ... LL | type T; - | ------- not a function or closure + | ------- not a function, impl block, or module + | + = help: coverage attribute can be applied to a function (with body), impl block, or module -error[E0788]: attribute should be applied to a function definition or closure +error[E0788]: coverage attribute not allowed here --> $DIR/name-value.rs:29:5 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ ... LL | const X: u32 = 7; - | ----------------- not a function or closure + | ----------------- not a function, impl block, or module + | + = help: coverage attribute can be applied to a function (with body), impl block, or module -error[E0788]: attribute should be applied to a function definition or closure +error[E0788]: coverage attribute not allowed here --> $DIR/name-value.rs:53:5 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ ... LL | const X: u32 = 8; - | ----------------- not a function or closure + | ----------------- not a function, impl block, or module + | + = help: coverage attribute can be applied to a function (with body), impl block, or module -error[E0788]: attribute should be applied to a function definition or closure +error[E0788]: coverage attribute not allowed here --> $DIR/name-value.rs:58:5 | LL | #[coverage = "off"] | ^^^^^^^^^^^^^^^^^^^ ... LL | type T = (); - | ------------ not a function or closure + | ------------ 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 diff --git a/tests/ui/coverage-attr/word-only.stderr b/tests/ui/coverage-attr/word-only.stderr index 97a0723988f51..bad50b0c961da 100644 --- a/tests/ui/coverage-attr/word-only.stderr +++ b/tests/ui/coverage-attr/word-only.stderr @@ -154,16 +154,18 @@ LL | #[coverage(off)] LL | #[coverage(on)] | -error[E0788]: attribute should be applied to a function definition or closure +error[E0788]: coverage attribute not allowed here --> $DIR/word-only.rs:21:1 | LL | #[coverage] | ^^^^^^^^^^^ ... LL | struct MyStruct; - | ---------------- not a function or closure + | ---------------- not a function, impl block, or module + | + = help: coverage attribute can be applied to a function (with body), impl block, or module -error[E0788]: attribute should be applied to a function definition or closure +error[E0788]: coverage attribute not allowed here --> $DIR/word-only.rs:35:1 | LL | #[coverage] @@ -174,52 +176,64 @@ LL | | #[coverage] ... | LL | | type T; LL | | } - | |_- not a function or closure + | |_- not a function, impl block, or module + | + = help: coverage attribute can be applied to a function (with body), impl block, or module -error[E0788]: attribute should be applied to a function definition or closure +error[E0788]: coverage attribute not allowed here --> $DIR/word-only.rs:39:5 | LL | #[coverage] | ^^^^^^^^^^^ ... LL | const X: u32; - | ------------- not a function or closure + | ------------- not a function, impl block, or module + | + = help: coverage attribute can be applied to a function (with body), impl block, or module -error[E0788]: attribute should be applied to a function definition or closure +error[E0788]: coverage attribute not allowed here --> $DIR/word-only.rs:44:5 | LL | #[coverage] | ^^^^^^^^^^^ ... LL | type T; - | ------- not a function or closure + | ------- not a function, impl block, or module + | + = help: coverage attribute can be applied to a function (with body), impl block, or module -error[E0788]: attribute should be applied to a function definition or closure +error[E0788]: coverage attribute not allowed here --> $DIR/word-only.rs:29:5 | LL | #[coverage] | ^^^^^^^^^^^ ... LL | const X: u32 = 7; - | ----------------- not a function or closure + | ----------------- not a function, impl block, or module + | + = help: coverage attribute can be applied to a function (with body), impl block, or module -error[E0788]: attribute should be applied to a function definition or closure +error[E0788]: coverage attribute not allowed here --> $DIR/word-only.rs:53:5 | LL | #[coverage] | ^^^^^^^^^^^ ... LL | const X: u32 = 8; - | ----------------- not a function or closure + | ----------------- not a function, impl block, or module + | + = help: coverage attribute can be applied to a function (with body), impl block, or module -error[E0788]: attribute should be applied to a function definition or closure +error[E0788]: coverage attribute not allowed here --> $DIR/word-only.rs:58:5 | LL | #[coverage] | ^^^^^^^^^^^ ... LL | type T = (); - | ------------ not a function or closure + | ------------ 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 From db02b1d3e951d28aa1ff0ad88efdb869ea85c14b Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 25 Dec 2024 15:18:01 +1100 Subject: [PATCH 5/6] Rewrite the error-code docs for coverage attributes [E0788] --- .../src/error_codes/E0788.md | 36 +++++++++---------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0788.md b/compiler/rustc_error_codes/src/error_codes/E0788.md index d655e51fa6636..ba138aed2d12f 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0788.md +++ b/compiler/rustc_error_codes/src/error_codes/E0788.md @@ -1,26 +1,24 @@ -A `#[coverage]` attribute was applied to something which does not show up -in code coverage, or is too granular to be excluded from the coverage report. +A `#[coverage(off|on)]` attribute was found in a position where it is not +allowed. -For now, this attribute can only be applied to function, method, and closure -definitions. In the future, it may be added to statements, blocks, and -expressions, and for the time being, using this attribute in those places -will just emit an `unused_attributes` lint instead of this error. +Coverage attributes can be applied to: +- Function and method declarations that have a body, including trait methods + that have a default implementation. +- Closure expressions, in situations where attributes can be applied to + expressions. +- `impl` blocks (inherent or trait), and modules. Example of erroneous code: ```compile_fail,E0788 -#[coverage(off)] -struct Foo; - -#[coverage(on)] -const FOO: Foo = Foo; +unsafe extern "C" { + #[coverage(off)] + fn foreign_fn(); +} ``` -`#[coverage(off)]` tells the compiler to not generate coverage instrumentation -for a piece of code when the `-C instrument-coverage` flag is passed. Things -like structs and consts are not coverable code, and thus cannot do anything -with this attribute. - -If you wish to apply this attribute to all methods in an impl or module, -manually annotate each method; it is not possible to annotate the entire impl -with a `#[coverage]` attribute. +When using the `-C instrument-coverage` flag, coverage attributes act as a +hint to the compiler that it should instrument or not instrument the +corresponding function or enclosed functions. The precise effect of applying +a coverage attribute is not guaranteed and may change in future compiler +versions. From e48fc62ce075985089f117e0472586be1af167b7 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 25 Dec 2024 16:15:28 +1100 Subject: [PATCH 6/6] Un-redact one occurrence of "coverage attribute not allowed here" --- tests/ui/coverage-attr/allowed-positions.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/coverage-attr/allowed-positions.rs b/tests/ui/coverage-attr/allowed-positions.rs index d4345c8d4432b..f1169fa657006 100644 --- a/tests/ui/coverage-attr/allowed-positions.rs +++ b/tests/ui/coverage-attr/allowed-positions.rs @@ -11,7 +11,7 @@ #[coverage(off)] mod submod {} -#[coverage(off)] //~ ERROR [E0788] +#[coverage(off)] //~ ERROR coverage attribute not allowed here [E0788] type MyTypeAlias = (); #[coverage(off)] //~ ERROR [E0788]