Add E0788 for improper #[no_coverage] usage

This commit is contained in:
ltdk 2022-05-28 17:20:43 -04:00
parent ebbcbfc236
commit 5fabdb8f7f
5 changed files with 202 additions and 0 deletions

View File

@ -491,6 +491,7 @@ E0784: include_str!("./error_codes/E0784.md"),
E0785: include_str!("./error_codes/E0785.md"),
E0786: include_str!("./error_codes/E0786.md"),
E0787: include_str!("./error_codes/E0787.md"),
E0788: include_str!("./error_codes/E0788.md"),
;
// E0006, // merged with E0005
// E0008, // cannot bind by-move into a pattern guard

View File

@ -0,0 +1,21 @@
A `#[no_coverage]` attribute was incorrectly placed on something that couldn't
be covered.
Example of erroneous code:
```compile_fail,E0788
#[no_coverage]
struct Foo;
#[no_coverage]
const FOO: Foo = Foo;
```
`#[no_coverage]` 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 `#[no_coverage]` attribute.

View File

@ -76,6 +76,7 @@ impl CheckAttrVisitor<'_> {
for attr in attrs {
let attr_is_valid = match attr.name_or_empty() {
sym::inline => self.check_inline(hir_id, attr, span, target),
sym::no_coverage => self.check_no_coverage(hir_id, attr, span, target),
sym::non_exhaustive => self.check_non_exhaustive(hir_id, attr, span, target),
sym::marker => self.check_marker(hir_id, attr, span, target),
sym::rustc_must_implement_one_of => {
@ -292,6 +293,56 @@ impl CheckAttrVisitor<'_> {
}
}
/// Checks if a `#[no_coverage]` is applied directly to a function
fn check_no_coverage(
&self,
hir_id: HirId,
attr: &Attribute,
span: Span,
target: Target,
) -> bool {
match target {
// no_coverage on function is fine
Target::Fn
| Target::Closure
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
// function prototypes can't be covered
Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => {
self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
lint.build("`#[no_coverage]` is ignored on function prototypes").emit();
});
true
}
Target::Mod | Target::ForeignMod | Target::Impl | Target::Trait => {
self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
lint.build("`#[no_coverage]` cannot be done recursively and must be applied to functions directly").emit();
});
true
}
Target::Expression | Target::Statement | Target::Arm => {
self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
lint.build("`#[no_coverage]` can only be applied at the function level, not on code directly").emit();
});
true
}
_ => {
struct_span_err!(
self.tcx.sess,
attr.span,
E0788,
"`#[no_coverage]` must be applied to coverable code",
)
.span_label(span, "not coverable code")
.emit();
false
}
}
}
fn check_generic_attr(
&self,
hir_id: HirId,

View File

@ -0,0 +1,46 @@
#![feature(extern_types)]
#![feature(no_coverage)]
#![feature(type_alias_impl_trait)]
#![warn(unused_attributes)]
trait Trait {
#[no_coverage] //~ ERROR `#[no_coverage]` must be applied to coverable code
const X: u32;
#[no_coverage] //~ ERROR `#[no_coverage]` must be applied to coverable code
type T;
type U;
}
impl Trait for () {
const X: u32 = 0;
#[no_coverage] //~ ERROR `#[no_coverage]` must be applied to coverable code
type T = Self;
#[no_coverage] //~ ERROR `#[no_coverage]` must be applied to coverable code
type U = impl Trait; //~ ERROR unconstrained opaque type
}
extern "C" {
#[no_coverage] //~ ERROR `#[no_coverage]` must be applied to coverable code
static X: u32;
#[no_coverage] //~ ERROR `#[no_coverage]` must be applied to coverable code
type T;
}
#[no_coverage]
fn main() {
#[no_coverage] //~ WARN `#[no_coverage]` can only be applied at the function level, not on code directly
let _ = ();
match () {
#[no_coverage] //~ WARN `#[no_coverage]` can only be applied at the function level, not on code directly
() => (),
}
#[no_coverage] //~ WARN `#[no_coverage]` can only be applied at the function level, not on code directly
return ();
}

View File

@ -0,0 +1,83 @@
warning: `#[no_coverage]` can only be applied at the function level, not on code directly
--> $DIR/no-coverage.rs:36:5
|
LL | #[no_coverage]
| ^^^^^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/no-coverage.rs:4:9
|
LL | #![warn(unused_attributes)]
| ^^^^^^^^^^^^^^^^^
warning: `#[no_coverage]` can only be applied at the function level, not on code directly
--> $DIR/no-coverage.rs:40:9
|
LL | #[no_coverage]
| ^^^^^^^^^^^^^^
warning: `#[no_coverage]` can only be applied at the function level, not on code directly
--> $DIR/no-coverage.rs:44:5
|
LL | #[no_coverage]
| ^^^^^^^^^^^^^^
error[E0788]: `#[no_coverage]` must be applied to coverable code
--> $DIR/no-coverage.rs:7:5
|
LL | #[no_coverage]
| ^^^^^^^^^^^^^^
LL | const X: u32;
| ------------- not coverable code
error[E0788]: `#[no_coverage]` must be applied to coverable code
--> $DIR/no-coverage.rs:10:5
|
LL | #[no_coverage]
| ^^^^^^^^^^^^^^
LL | type T;
| ------- not coverable code
error[E0788]: `#[no_coverage]` must be applied to coverable code
--> $DIR/no-coverage.rs:19:5
|
LL | #[no_coverage]
| ^^^^^^^^^^^^^^
LL | type T = Self;
| -------------- not coverable code
error[E0788]: `#[no_coverage]` must be applied to coverable code
--> $DIR/no-coverage.rs:22:5
|
LL | #[no_coverage]
| ^^^^^^^^^^^^^^
LL | type U = impl Trait;
| -------------------- not coverable code
error[E0788]: `#[no_coverage]` must be applied to coverable code
--> $DIR/no-coverage.rs:27:5
|
LL | #[no_coverage]
| ^^^^^^^^^^^^^^
LL | static X: u32;
| -------------- not coverable code
error[E0788]: `#[no_coverage]` must be applied to coverable code
--> $DIR/no-coverage.rs:30:5
|
LL | #[no_coverage]
| ^^^^^^^^^^^^^^
LL | type T;
| ------- not coverable code
error: unconstrained opaque type
--> $DIR/no-coverage.rs:23:14
|
LL | type U = impl Trait;
| ^^^^^^^^^^
|
= note: `U` must be used in combination with a concrete type within the same module
error: aborting due to 7 previous errors; 3 warnings emitted
For more information about this error, try `rustc --explain E0788`.