Add E0788 for improper #[no_coverage] usage
This commit is contained in:
parent
ebbcbfc236
commit
5fabdb8f7f
5 changed files with 202 additions and 0 deletions
|
@ -491,6 +491,7 @@ E0784: include_str!("./error_codes/E0784.md"),
|
||||||
E0785: include_str!("./error_codes/E0785.md"),
|
E0785: include_str!("./error_codes/E0785.md"),
|
||||||
E0786: include_str!("./error_codes/E0786.md"),
|
E0786: include_str!("./error_codes/E0786.md"),
|
||||||
E0787: include_str!("./error_codes/E0787.md"),
|
E0787: include_str!("./error_codes/E0787.md"),
|
||||||
|
E0788: include_str!("./error_codes/E0788.md"),
|
||||||
;
|
;
|
||||||
// E0006, // merged with E0005
|
// E0006, // merged with E0005
|
||||||
// E0008, // cannot bind by-move into a pattern guard
|
// E0008, // cannot bind by-move into a pattern guard
|
||||||
|
|
21
compiler/rustc_error_codes/src/error_codes/E0788.md
Normal file
21
compiler/rustc_error_codes/src/error_codes/E0788.md
Normal 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.
|
|
@ -76,6 +76,7 @@ impl CheckAttrVisitor<'_> {
|
||||||
for attr in attrs {
|
for attr in attrs {
|
||||||
let attr_is_valid = match attr.name_or_empty() {
|
let attr_is_valid = match attr.name_or_empty() {
|
||||||
sym::inline => self.check_inline(hir_id, attr, span, target),
|
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::non_exhaustive => self.check_non_exhaustive(hir_id, attr, span, target),
|
||||||
sym::marker => self.check_marker(hir_id, attr, span, target),
|
sym::marker => self.check_marker(hir_id, attr, span, target),
|
||||||
sym::rustc_must_implement_one_of => {
|
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(
|
fn check_generic_attr(
|
||||||
&self,
|
&self,
|
||||||
hir_id: HirId,
|
hir_id: HirId,
|
||||||
|
|
46
src/test/ui/lint/no-coverage.rs
Normal file
46
src/test/ui/lint/no-coverage.rs
Normal 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 ();
|
||||||
|
}
|
83
src/test/ui/lint/no-coverage.stderr
Normal file
83
src/test/ui/lint/no-coverage.stderr
Normal 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`.
|
Loading…
Add table
Add a link
Reference in a new issue