Auto merge of #114656 - bossmc:rework-no-coverage-attr, r=oli-obk

Rework `no_coverage` to `coverage(off)`

As discussed at the tail of https://github.com/rust-lang/rust/issues/84605 this replaces the `no_coverage` attribute with a `coverage` attribute that takes sub-parameters (currently `off` and `on`) to control the coverage instrumentation.

Allows future-proofing for things like `coverage(off, reason="Tested live", issue="#12345")` or similar.
This commit is contained in:
bors 2023-09-14 01:05:18 +00:00
commit c728bf3963
38 changed files with 253 additions and 213 deletions

View File

@ -34,7 +34,7 @@ pub fn expand_deriving_eq(
attributes: thin_vec![
cx.attr_word(sym::inline, span),
cx.attr_nested_word(sym::doc, sym::hidden, span),
cx.attr_word(sym::no_coverage, span)
cx.attr_nested_word(sym::coverage, sym::off, span)
],
fieldless_variants_strategy: FieldlessVariantsStrategy::Unify,
combine_substructure: combine_substructure(Box::new(|a, b, c| {

View File

@ -254,7 +254,7 @@ fn generate_test_harness(
let expn_id = ext_cx.resolver.expansion_for_ast_pass(
DUMMY_SP,
AstPass::TestHarness,
&[sym::test, sym::rustc_attrs, sym::no_coverage],
&[sym::test, sym::rustc_attrs, sym::coverage_attribute],
None,
);
let def_site = DUMMY_SP.with_def_site_ctxt(expn_id.to_expn_id());
@ -335,8 +335,8 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
// #[rustc_main]
let main_attr = ecx.attr_word(sym::rustc_main, sp);
// #[no_coverage]
let no_coverage_attr = ecx.attr_word(sym::no_coverage, sp);
// #[coverage(off)]
let coverage_attr = ecx.attr_nested_word(sym::coverage, sym::off, sp);
// pub fn main() { ... }
let main_ret_ty = ecx.ty(sp, ast::TyKind::Tup(ThinVec::new()));
@ -366,7 +366,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
let main = P(ast::Item {
ident: main_id,
attrs: thin_vec![main_attr, no_coverage_attr],
attrs: thin_vec![main_attr, coverage_attr],
id: ast::DUMMY_NODE_ID,
kind: main,
vis: ast::Visibility { span: sp, kind: ast::VisibilityKind::Public, tokens: None },

View File

@ -330,10 +330,10 @@ fn add_unused_functions(cx: &CodegenCx<'_, '_>) {
{
let codegen_fn_attrs = tcx.codegen_fn_attrs(non_codegenned_def_id);
// If a function is marked `#[no_coverage]`, then skip generating a
// If a function is marked `#[coverage(off)]`, then skip generating a
// dead code stub for it.
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NO_COVERAGE) {
debug!("skipping unused fn marked #[no_coverage]: {:?}", non_codegenned_def_id);
debug!("skipping unused fn marked #[coverage(off)]: {:?}", non_codegenned_def_id);
continue;
}

View File

@ -23,6 +23,8 @@ codegen_ssa_erroneous_constant = erroneous constant encountered
codegen_ssa_error_creating_remark_dir = failed to create remark directory: {$error}
codegen_ssa_expected_coverage_symbol = expected `coverage(off)` or `coverage(on)`
codegen_ssa_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
codegen_ssa_extern_funcs_not_found = some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified

View File

@ -16,7 +16,10 @@ use rustc_target::spec::{abi, SanitizerSet};
use crate::errors;
use crate::target_features::from_target_feature;
use crate::{errors::ExpectedUsedSymbol, target_features::check_target_feature_trait_unsafe};
use crate::{
errors::{ExpectedCoverageSymbol, ExpectedUsedSymbol},
target_features::check_target_feature_trait_unsafe,
};
fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage {
use rustc_middle::mir::mono::Linkage::*;
@ -128,7 +131,21 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
.emit();
}
}
sym::no_coverage => codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE,
sym::coverage => {
let inner = attr.meta_item_list();
match inner.as_deref() {
Some([item]) if item.has_name(sym::off) => {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE;
}
Some([item]) if item.has_name(sym::on) => {
// Allow #[coverage(on)] for being explicit, maybe also in future to enable
// coverage on a smaller scope within an excluded larger scope.
}
Some(_) | None => {
tcx.sess.emit_err(ExpectedCoverageSymbol { span: attr.span });
}
}
}
sym::rustc_std_internal_symbol => {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL
}

View File

@ -561,6 +561,13 @@ pub struct UnknownArchiveKind<'a> {
pub kind: &'a str,
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_expected_coverage_symbol)]
pub struct ExpectedCoverageSymbol {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(codegen_ssa_expected_used_symbol)]
pub struct ExpectedUsedSymbol {

View File

@ -1,4 +1,4 @@
A `#[no_coverage]` attribute was applied to something which does not show up
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.
For now, this attribute can only be applied to function, method, and closure
@ -9,18 +9,18 @@ will just emit an `unused_attributes` lint instead of this error.
Example of erroneous code:
```compile_fail,E0788
#[no_coverage]
#[coverage(off)]
struct Foo;
#[no_coverage]
#[coverage(on)]
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.
`#[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 `#[no_coverage]` attribute.
with a `#[coverage]` attribute.

View File

@ -398,6 +398,9 @@ declare_features! (
(active, const_trait_impl, "1.42.0", Some(67792), None),
/// Allows the `?` operator in const contexts.
(active, const_try, "1.56.0", Some(74935), None),
/// Allows function attribute `#[coverage(on/off)]`, to control coverage
/// instrumentation of that function.
(active, coverage_attribute, "CURRENT_RUSTC_VERSION", Some(84605), None),
/// Allows non-builtin attributes in inner attribute position.
(active, custom_inner_attributes, "1.30.0", Some(54726), None),
/// Allows custom test frameworks with `#![test_runner]` and `#[test_case]`.
@ -509,9 +512,6 @@ declare_features! (
(active, never_type_fallback, "1.41.0", Some(65992), None),
/// Allows `#![no_core]`.
(active, no_core, "1.3.0", Some(29639), None),
/// Allows function attribute `#[no_coverage]`, to bypass coverage
/// instrumentation of that function.
(active, no_coverage, "1.53.0", Some(84605), None),
/// Allows the use of `no_sanitize` attribute.
(active, no_sanitize, "1.42.0", Some(39699), None),
/// Allows using the `non_exhaustive_omitted_patterns` lint.

View File

@ -395,7 +395,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
template!(List: "address, kcfi, memory, thread"), DuplicatesOk,
experimental!(no_sanitize)
),
gated!(no_coverage, Normal, template!(Word), WarnFollowing, experimental!(no_coverage)),
gated!(coverage, Normal, template!(Word, List: "on|off"), WarnFollowing, coverage_attribute, experimental!(coverage)),
ungated!(
doc, Normal, template!(List: "hidden|inline|...", NameValueStr: "string"), DuplicatesOk

View File

@ -136,6 +136,9 @@ declare_features! (
Some("subsumed by `#![feature(allocator_internals)]`")),
/// Allows use of unary negate on unsigned integers, e.g., -e for e: u8
(removed, negate_unsigned, "1.0.0", Some(29645), None, None),
/// Allows `#[no_coverage]` on functions.
/// The feature was renamed to `coverage` and the attribute to `#[coverage(on|off)]`
(removed, no_coverage, "CURRENT_RUSTC_VERSION", Some(84605), None, Some("renamed to `coverage`")),
/// Allows `#[no_debug]`.
(removed, no_debug, "1.43.0", Some(29721), None, Some("removed due to lack of demand")),
/// Allows using `#[on_unimplemented(..)]` on traits.

View File

@ -87,7 +87,7 @@ bitflags! {
/// #[cmse_nonsecure_entry]: with a TrustZone-M extension, declare a
/// function as an entry function from Non-Secure code.
const CMSE_NONSECURE_ENTRY = 1 << 14;
/// `#[no_coverage]`: indicates that the function should be ignored by
/// `#[coverage(off)]`: indicates that the function should be ignored by
/// the MIR `InstrumentCoverage` pass and not added to the coverage map
/// during codegen.
const NO_COVERAGE = 1 << 15;

View File

@ -109,6 +109,19 @@ passes_continue_labeled_block =
.label = labeled blocks cannot be `continue`'d
.block_label = labeled block the `continue` points to
passes_coverage_fn_defn =
`#[coverage]` may only be applied to function definitions
passes_coverage_ignored_function_prototype =
`#[coverage]` is ignored on function prototypes
passes_coverage_not_coverable =
`#[coverage]` must be applied to coverable code
.label = not coverable code
passes_coverage_propagate =
`#[coverage]` does not propagate into items and must be applied to the contained functions directly
passes_dead_codes =
{ $multiple ->
*[true] multiple {$descr}s are
@ -499,19 +512,6 @@ passes_naked_functions_operands =
passes_naked_tracked_caller =
cannot use `#[track_caller]` with `#[naked]`
passes_no_coverage_fn_defn =
`#[no_coverage]` may only be applied to function definitions
passes_no_coverage_ignored_function_prototype =
`#[no_coverage]` is ignored on function prototypes
passes_no_coverage_not_coverable =
`#[no_coverage]` must be applied to coverable code
.label = not coverable code
passes_no_coverage_propagate =
`#[no_coverage]` does not propagate into items and must be applied to the contained functions directly
passes_no_link =
attribute should be applied to an `extern crate` item
.label = not an `extern crate` item

View File

@ -107,7 +107,7 @@ impl CheckAttrVisitor<'_> {
match attr.name_or_empty() {
sym::do_not_recommend => self.check_do_not_recommend(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::coverage => self.check_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::target_feature => self.check_target_feature(hir_id, attr, span, target),
@ -327,16 +327,10 @@ 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 {
/// Checks if a `#[coverage]` is applied directly to a function
fn check_coverage(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool {
match target {
// no_coverage on function is fine
// #[coverage] on function is fine
Target::Fn
| Target::Closure
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
@ -347,7 +341,7 @@ impl CheckAttrVisitor<'_> {
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
errors::IgnoredNoCoverageFnProto,
errors::IgnoredCoverageFnProto,
);
true
}
@ -357,7 +351,7 @@ impl CheckAttrVisitor<'_> {
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
errors::IgnoredNoCoveragePropagate,
errors::IgnoredCoveragePropagate,
);
true
}
@ -367,13 +361,13 @@ impl CheckAttrVisitor<'_> {
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
errors::IgnoredNoCoverageFnDefn,
errors::IgnoredCoverageFnDefn,
);
true
}
_ => {
self.tcx.sess.emit_err(errors::IgnoredNoCoverageNotCoverable {
self.tcx.sess.emit_err(errors::IgnoredCoverageNotCoverable {
attr_span: attr.span,
defn_span: span,
});

View File

@ -64,20 +64,20 @@ pub struct InlineNotFnOrClosure {
}
#[derive(LintDiagnostic)]
#[diag(passes_no_coverage_ignored_function_prototype)]
pub struct IgnoredNoCoverageFnProto;
#[diag(passes_coverage_ignored_function_prototype)]
pub struct IgnoredCoverageFnProto;
#[derive(LintDiagnostic)]
#[diag(passes_no_coverage_propagate)]
pub struct IgnoredNoCoveragePropagate;
#[diag(passes_coverage_propagate)]
pub struct IgnoredCoveragePropagate;
#[derive(LintDiagnostic)]
#[diag(passes_no_coverage_fn_defn)]
pub struct IgnoredNoCoverageFnDefn;
#[diag(passes_coverage_fn_defn)]
pub struct IgnoredCoverageFnDefn;
#[derive(Diagnostic)]
#[diag(passes_no_coverage_not_coverable, code = "E0788")]
pub struct IgnoredNoCoverageNotCoverable {
#[diag(passes_coverage_not_coverable, code = "E0788")]
pub struct IgnoredCoverageNotCoverable {
#[primary_span]
pub attr_span: Span,
#[label]

View File

@ -574,6 +574,8 @@ symbols! {
cosf32,
cosf64,
count,
coverage,
coverage_attribute,
cr,
crate_id,
crate_in_paths,
@ -1069,6 +1071,7 @@ symbols! {
note,
object_safe_for_dispatch,
of,
off,
offset,
offset_of,
omit_gdb_pretty_printer_section,

View File

@ -289,7 +289,8 @@ pub trait Eq: PartialEq<Self> {
//
// This should never be implemented by hand.
#[doc(hidden)]
#[no_coverage] // rust-lang/rust#84605
#[cfg_attr(bootstrap, no_coverage)] // rust-lang/rust#84605
#[cfg_attr(not(bootstrap), coverage(off))] //
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
fn assert_receiver_is_total_eq(&self) {}
@ -298,7 +299,9 @@ pub trait Eq: PartialEq<Self> {
/// Derive macro generating an impl of the trait [`Eq`].
#[rustc_builtin_macro]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[allow_internal_unstable(core_intrinsics, derive_eq, structural_match, no_coverage)]
#[allow_internal_unstable(core_intrinsics, derive_eq, structural_match)]
#[cfg_attr(bootstrap, allow_internal_unstable(no_coverage))]
#[cfg_attr(not(bootstrap), allow_internal_unstable(coverage_attribute))]
pub macro Eq($item:item) {
/* compiler built-in */
}

View File

@ -110,6 +110,8 @@
//
// Library features:
// tidy-alphabetical-start
#![cfg_attr(bootstrap, feature(no_coverage))] // rust-lang/rust#84605
#![cfg_attr(not(bootstrap), feature(coverage_attribute))] // rust-lang/rust#84605
#![feature(char_indices_offset)]
#![feature(const_align_of_val)]
#![feature(const_align_of_val_raw)]
@ -235,7 +237,6 @@
#![feature(negative_impls)]
#![feature(never_type)]
#![feature(no_core)]
#![feature(no_coverage)] // rust-lang/rust#84605
#![feature(platform_intrinsics)]
#![feature(prelude_import)]
#![feature(repr_simd)]

View File

@ -173,9 +173,9 @@ Some of the more notable options in this example include:
[`llvm-cov report`]: https://llvm.org/docs/CommandGuide/llvm-cov.html#llvm-cov-report
[`llvm-cov show`]: https://llvm.org/docs/CommandGuide/llvm-cov.html#llvm-cov-show
> **Note**: Coverage can also be disabled on an individual function by annotating the function with the [`no_coverage` attribute] (which requires the feature flag `#![feature(no_coverage)]`).
> **Note**: Coverage can also be disabled on an individual function by annotating the function with the [`coverage(off)` attribute] (which requires the feature flag `#![feature(coverage)]`).
[`no_coverage` attribute]: ../unstable-book/language-features/no-coverage.html
[`coverage` attribute]: ../unstable-book/language-features/coverage.html
## Interpreting reports

View File

@ -1,4 +1,4 @@
# `no_coverage`
# `coverage_attribute`
The tracking issue for this feature is: [#84605]
@ -6,7 +6,7 @@ The tracking issue for this feature is: [#84605]
---
The `no_coverage` attribute can be used to selectively disable coverage
The `coverage` attribute can be used to selectively disable coverage
instrumentation in an annotated function. This might be useful to:
- Avoid instrumentation overhead in a performance critical function
@ -16,14 +16,14 @@ instrumentation in an annotated function. This might be useful to:
## Example
```rust
#![feature(no_coverage)]
#![feature(coverage_attribute)]
// `foo()` will get coverage instrumentation (by default)
fn foo() {
// ...
}
#[no_coverage]
#[coverage(off)]
fn bar() {
// ...
}

View File

@ -239,7 +239,7 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[
template!(List: "address, kcfi, memory, thread"), DuplicatesOk,
experimental!(no_sanitize)
),
gated!(no_coverage, Normal, template!(Word), WarnFollowing, experimental!(no_coverage)),
gated!(coverage, Normal, template!(Word, List: "on|off"), WarnFollowing, experimental!(coverage)),
ungated!(
doc, Normal, template!(List: "hidden|inline|...", NameValueStr: "string"), DuplicatesOk

View File

@ -3505,8 +3505,8 @@ This serves two purposes:
"##,
},
Lint {
label: "no_coverage",
description: r##"# `no_coverage`
label: "coverage",
description: r##"# `coverage`
The tracking issue for this feature is: [#84605]
@ -3514,7 +3514,7 @@ The tracking issue for this feature is: [#84605]
---
The `no_coverage` attribute can be used to selectively disable coverage
The `coverage` attribute can be used to selectively disable coverage
instrumentation in an annotated function. This might be useful to:
- Avoid instrumentation overhead in a performance critical function
@ -3524,14 +3524,14 @@ instrumentation in an annotated function. This might be useful to:
## Example
```rust
#![feature(no_coverage)]
#![feature(coverage)]
// `foo()` will get coverage instrumentation (by default)
fn foo() {
// ...
}
#[no_coverage]
#[coverage(off)]
fn bar() {
// ...
}

View File

@ -1,5 +1,5 @@
// compile-flags: --edition=2018
#![feature(no_coverage)]
#![feature(coverage_attribute)]
macro_rules! bail {
($msg:literal $(,)?) => {

View File

@ -1,5 +1,5 @@
// compile-flags: --edition=2018
#![feature(no_coverage)]
#![feature(coverage_attribute)]
macro_rules! bail {
($msg:literal $(,)?) => {
@ -39,7 +39,7 @@ pub async fn test() -> Result<(), String> {
Ok(())
}
#[no_coverage]
#[coverage(off)]
fn main() {
executor::block_on(test()).unwrap();
}
@ -51,18 +51,18 @@ mod executor {
task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
};
#[no_coverage]
#[coverage(off)]
pub fn block_on<F: Future>(mut future: F) -> F::Output {
let mut future = unsafe { Pin::new_unchecked(&mut future) };
use std::hint::unreachable_unchecked;
static VTABLE: RawWakerVTable = RawWakerVTable::new(
#[no_coverage]
#[coverage(off)]
|_| unsafe { unreachable_unchecked() }, // clone
#[no_coverage]
#[coverage(off)]
|_| unsafe { unreachable_unchecked() }, // wake
#[no_coverage]
#[coverage(off)]
|_| unsafe { unreachable_unchecked() }, // wake_by_ref
#[no_coverage]
#[coverage(off)]
|_| (),
);
let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };

View File

@ -1,17 +1,17 @@
// Enables `no_coverage` on the entire crate
#![feature(no_coverage)]
// Enables `coverage(off)` on the entire crate
#![feature(coverage_attribute)]
#[no_coverage]
#[coverage(off)]
fn do_not_add_coverage_1() {
println!("called but not covered");
}
fn do_not_add_coverage_2() {
#![no_coverage]
#![coverage(off)]
println!("called but not covered");
}
#[no_coverage]
#[coverage(off)]
#[allow(dead_code)]
fn do_not_add_coverage_not_called() {
println!("not called and not covered");
@ -33,7 +33,7 @@ fn add_coverage_not_called() {
// FIXME: These test-cases illustrate confusing results of nested functions.
// See https://github.com/rust-lang/rust/issues/93319
mod nested_fns {
#[no_coverage]
#[coverage(off)]
pub fn outer_not_covered(is_true: bool) {
fn inner(is_true: bool) {
if is_true {
@ -50,7 +50,7 @@ mod nested_fns {
println!("called and covered");
inner_not_covered(is_true);
#[no_coverage]
#[coverage(off)]
fn inner_not_covered(is_true: bool) {
if is_true {
println!("called but not covered");

View File

@ -79,7 +79,7 @@ pub const a_test: test::TestDescAndFn =
};
fn a_test() {}
#[rustc_main]
#[no_coverage]
#[coverage(off)]
pub fn main() -> () {
extern crate test;
test::test_main_static(&[&a_test, &m_test, &z_test])

View File

@ -1,5 +1,5 @@
LL| |// compile-flags: --edition=2018
LL| |#![feature(no_coverage)]
LL| |#![feature(coverage_attribute)]
LL| |
LL| |macro_rules! bail {
LL| | ($msg:literal $(,)?) => {

View File

@ -1,5 +1,5 @@
// compile-flags: --edition=2018
#![feature(no_coverage)]
#![feature(coverage_attribute)]
macro_rules! bail {
($msg:literal $(,)?) => {

View File

@ -1,5 +1,5 @@
LL| |// compile-flags: --edition=2018
LL| |#![feature(no_coverage)]
LL| |#![feature(coverage_attribute)]
LL| |
LL| |macro_rules! bail {
LL| | ($msg:literal $(,)?) => {
@ -40,7 +40,7 @@
LL| 1| Ok(())
LL| 1|}
LL| |
LL| |#[no_coverage]
LL| |#[coverage(off)]
LL| |fn main() {
LL| | executor::block_on(test()).unwrap();
LL| |}
@ -52,18 +52,18 @@
LL| | task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
LL| | };
LL| |
LL| | #[no_coverage]
LL| | #[coverage(off)]
LL| | pub fn block_on<F: Future>(mut future: F) -> F::Output {
LL| | let mut future = unsafe { Pin::new_unchecked(&mut future) };
LL| | use std::hint::unreachable_unchecked;
LL| | static VTABLE: RawWakerVTable = RawWakerVTable::new(
LL| | #[no_coverage]
LL| | #[coverage(off)]
LL| | |_| unsafe { unreachable_unchecked() }, // clone
LL| | #[no_coverage]
LL| | #[coverage(off)]
LL| | |_| unsafe { unreachable_unchecked() }, // wake
LL| | #[no_coverage]
LL| | #[coverage(off)]
LL| | |_| unsafe { unreachable_unchecked() }, // wake_by_ref
LL| | #[no_coverage]
LL| | #[coverage(off)]
LL| | |_| (),
LL| | );
LL| | let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };

View File

@ -1,5 +1,5 @@
// compile-flags: --edition=2018
#![feature(no_coverage)]
#![feature(coverage_attribute)]
macro_rules! bail {
($msg:literal $(,)?) => {
@ -39,7 +39,7 @@ pub async fn test() -> Result<(), String> {
Ok(())
}
#[no_coverage]
#[coverage(off)]
fn main() {
executor::block_on(test()).unwrap();
}
@ -51,18 +51,18 @@ mod executor {
task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
};
#[no_coverage]
#[coverage(off)]
pub fn block_on<F: Future>(mut future: F) -> F::Output {
let mut future = unsafe { Pin::new_unchecked(&mut future) };
use std::hint::unreachable_unchecked;
static VTABLE: RawWakerVTable = RawWakerVTable::new(
#[no_coverage]
#[coverage(off)]
|_| unsafe { unreachable_unchecked() }, // clone
#[no_coverage]
#[coverage(off)]
|_| unsafe { unreachable_unchecked() }, // wake
#[no_coverage]
#[coverage(off)]
|_| unsafe { unreachable_unchecked() }, // wake_by_ref
#[no_coverage]
#[coverage(off)]
|_| (),
);
let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };

View File

@ -1,17 +1,17 @@
LL| |// Enables `no_coverage` on the entire crate
LL| |#![feature(no_coverage)]
LL| |// Enables `coverage(off)` on the entire crate
LL| |#![feature(coverage_attribute)]
LL| |
LL| |#[no_coverage]
LL| |#[coverage(off)]
LL| |fn do_not_add_coverage_1() {
LL| | println!("called but not covered");
LL| |}
LL| |
LL| |fn do_not_add_coverage_2() {
LL| | #![no_coverage]
LL| | #![coverage(off)]
LL| | println!("called but not covered");
LL| |}
LL| |
LL| |#[no_coverage]
LL| |#[coverage(off)]
LL| |#[allow(dead_code)]
LL| |fn do_not_add_coverage_not_called() {
LL| | println!("not called and not covered");
@ -33,7 +33,7 @@
LL| |// FIXME: These test-cases illustrate confusing results of nested functions.
LL| |// See https://github.com/rust-lang/rust/issues/93319
LL| |mod nested_fns {
LL| | #[no_coverage]
LL| | #[coverage(off)]
LL| | pub fn outer_not_covered(is_true: bool) {
LL| 1| fn inner(is_true: bool) {
LL| 1| if is_true {
@ -50,7 +50,7 @@
LL| 1| println!("called and covered");
LL| 1| inner_not_covered(is_true);
LL| 1|
LL| 1| #[no_coverage]
LL| 1| #[coverage(off)]
LL| 1| fn inner_not_covered(is_true: bool) {
LL| 1| if is_true {
LL| 1| println!("called but not covered");

View File

@ -1,17 +1,17 @@
// Enables `no_coverage` on the entire crate
#![feature(no_coverage)]
// Enables `coverage(off)` on the entire crate
#![feature(coverage_attribute)]
#[no_coverage]
#[coverage(off)]
fn do_not_add_coverage_1() {
println!("called but not covered");
}
fn do_not_add_coverage_2() {
#![no_coverage]
#![coverage(off)]
println!("called but not covered");
}
#[no_coverage]
#[coverage(off)]
#[allow(dead_code)]
fn do_not_add_coverage_not_called() {
println!("not called and not covered");
@ -33,7 +33,7 @@ fn add_coverage_not_called() {
// FIXME: These test-cases illustrate confusing results of nested functions.
// See https://github.com/rust-lang/rust/issues/93319
mod nested_fns {
#[no_coverage]
#[coverage(off)]
pub fn outer_not_covered(is_true: bool) {
fn inner(is_true: bool) {
if is_true {
@ -50,7 +50,7 @@ mod nested_fns {
println!("called and covered");
inner_not_covered(is_true);
#[no_coverage]
#[coverage(off)]
fn inner_not_covered(is_true: bool) {
if is_true {
println!("called but not covered");

View File

@ -60,7 +60,7 @@ impl ::core::marker::StructuralEq for Empty { }
impl ::core::cmp::Eq for Empty {
#[inline]
#[doc(hidden)]
#[no_coverage]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {}
}
#[automatically_derived]
@ -135,7 +135,7 @@ impl ::core::marker::StructuralEq for Point { }
impl ::core::cmp::Eq for Point {
#[inline]
#[doc(hidden)]
#[no_coverage]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<u32>;
}
@ -221,7 +221,7 @@ impl ::core::marker::StructuralEq for PackedPoint { }
impl ::core::cmp::Eq for PackedPoint {
#[inline]
#[doc(hidden)]
#[no_coverage]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<u32>;
}
@ -334,7 +334,7 @@ impl ::core::marker::StructuralEq for Big { }
impl ::core::cmp::Eq for Big {
#[inline]
#[doc(hidden)]
#[no_coverage]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<u32>;
}
@ -500,7 +500,7 @@ impl ::core::marker::StructuralEq for Unsized { }
impl ::core::cmp::Eq for Unsized {
#[inline]
#[doc(hidden)]
#[no_coverage]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<[u32]>;
}
@ -615,7 +615,7 @@ impl<T: ::core::cmp::Eq + Trait, U: ::core::cmp::Eq> ::core::cmp::Eq for
Generic<T, U> where T::A: ::core::cmp::Eq {
#[inline]
#[doc(hidden)]
#[no_coverage]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<T>;
let _: ::core::cmp::AssertParamIsEq<T::A>;
@ -738,7 +738,7 @@ impl<T: ::core::cmp::Eq + ::core::marker::Copy + Trait, U: ::core::cmp::Eq +
T::A: ::core::cmp::Eq + ::core::marker::Copy {
#[inline]
#[doc(hidden)]
#[no_coverage]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<T>;
let _: ::core::cmp::AssertParamIsEq<T::A>;
@ -821,7 +821,7 @@ impl ::core::marker::StructuralEq for Enum0 { }
impl ::core::cmp::Eq for Enum0 {
#[inline]
#[doc(hidden)]
#[no_coverage]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {}
}
#[automatically_derived]
@ -892,7 +892,7 @@ impl ::core::marker::StructuralEq for Enum1 { }
impl ::core::cmp::Eq for Enum1 {
#[inline]
#[doc(hidden)]
#[no_coverage]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<u32>;
}
@ -959,7 +959,7 @@ impl ::core::marker::StructuralEq for Fieldless1 { }
impl ::core::cmp::Eq for Fieldless1 {
#[inline]
#[doc(hidden)]
#[no_coverage]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {}
}
#[automatically_derived]
@ -1034,7 +1034,7 @@ impl ::core::marker::StructuralEq for Fieldless { }
impl ::core::cmp::Eq for Fieldless {
#[inline]
#[doc(hidden)]
#[no_coverage]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {}
}
#[automatically_derived]
@ -1142,7 +1142,7 @@ impl ::core::marker::StructuralEq for Mixed { }
impl ::core::cmp::Eq for Mixed {
#[inline]
#[doc(hidden)]
#[no_coverage]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<u32>;
let _: ::core::cmp::AssertParamIsEq<Option<u32>>;
@ -1270,7 +1270,7 @@ impl ::core::marker::StructuralEq for Fielded { }
impl ::core::cmp::Eq for Fielded {
#[inline]
#[doc(hidden)]
#[no_coverage]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<u32>;
let _: ::core::cmp::AssertParamIsEq<bool>;
@ -1393,7 +1393,7 @@ impl<T: ::core::cmp::Eq, U: ::core::cmp::Eq> ::core::cmp::Eq for
EnumGeneric<T, U> {
#[inline]
#[doc(hidden)]
#[no_coverage]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<T>;
let _: ::core::cmp::AssertParamIsEq<U>;

View File

@ -0,0 +1,14 @@
#![crate_type = "lib"]
#![feature(no_coverage)] //~ ERROR feature has been removed [E0557]
#[derive(PartialEq, Eq)] // ensure deriving `Eq` does not enable `feature(coverage)`
struct Foo {
a: u8,
b: u32,
}
#[coverage(off)] //~ ERROR the `#[coverage]` attribute is an experimental feature
fn requires_feature_coverage() -> bool {
let bar = Foo { a: 0, b: 0 };
bar == Foo { a: 0, b: 0 }
}

View File

@ -0,0 +1,21 @@
error[E0557]: feature has been removed
--> $DIR/feature-gate-coverage-attribute.rs:2:12
|
LL | #![feature(no_coverage)]
| ^^^^^^^^^^^ feature has been removed
|
= note: renamed to `coverage`
error[E0658]: the `#[coverage]` attribute is an experimental feature
--> $DIR/feature-gate-coverage-attribute.rs:10:1
|
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^
|
= 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
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0557, E0658.
For more information about an error, try `rustc --explain E0557`.

View File

@ -1,13 +0,0 @@
#![crate_type = "lib"]
#[derive(PartialEq, Eq)] // ensure deriving `Eq` does not enable `feature(no_coverage)`
struct Foo {
a: u8,
b: u32,
}
#[no_coverage] //~ ERROR the `#[no_coverage]` attribute is an experimental feature
fn requires_feature_no_coverage() -> bool {
let bar = Foo { a: 0, b: 0 };
bar == Foo { a: 0, b: 0 }
}

View File

@ -1,12 +0,0 @@
error[E0658]: the `#[no_coverage]` attribute is an experimental feature
--> $DIR/feature-gate-no_coverage.rs:9:1
|
LL | #[no_coverage]
| ^^^^^^^^^^^^^^
|
= note: see issue #84605 <https://github.com/rust-lang/rust/issues/84605> for more information
= help: add `#![feature(no_coverage)]` to the crate attributes to enable
error: aborting due to previous error
For more information about this error, try `rustc --explain E0658`.

View File

@ -1,55 +1,55 @@
#![feature(extern_types)]
#![feature(no_coverage)]
#![feature(coverage_attribute)]
#![feature(impl_trait_in_assoc_type)]
#![warn(unused_attributes)]
#![no_coverage]
//~^ WARN: `#[no_coverage]` does not propagate into items and must be applied to the contained functions directly
#![coverage(off)]
//~^ WARN: `#[coverage]` does not propagate into items and must be applied to the contained functions directly
#[no_coverage]
//~^ WARN: `#[no_coverage]` does not propagate into items and must be applied to the contained functions directly
#[coverage(off)]
//~^ WARN: `#[coverage]` does not propagate into items and must be applied to the contained functions directly
trait Trait {
#[no_coverage] //~ ERROR `#[no_coverage]` must be applied to coverable code
#[coverage(off)] //~ ERROR `#[coverage]` must be applied to coverable code
const X: u32;
#[no_coverage] //~ ERROR `#[no_coverage]` must be applied to coverable code
#[coverage(off)] //~ ERROR `#[coverage]` must be applied to coverable code
type T;
type U;
}
#[no_coverage]
//~^ WARN: `#[no_coverage]` does not propagate into items and must be applied to the contained functions directly
#[coverage(off)]
//~^ WARN: `#[coverage]` does not propagate into items and must be applied to the contained functions directly
impl Trait for () {
const X: u32 = 0;
#[no_coverage] //~ ERROR `#[no_coverage]` must be applied to coverable code
#[coverage(off)] //~ ERROR `#[coverage]` must be applied to coverable code
type T = Self;
#[no_coverage] //~ ERROR `#[no_coverage]` must be applied to coverable code
#[coverage(off)] //~ ERROR `#[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
#[coverage(off)] //~ ERROR `#[coverage]` must be applied to coverable code
static X: u32;
#[no_coverage] //~ ERROR `#[no_coverage]` must be applied to coverable code
#[coverage(off)] //~ ERROR `#[coverage]` must be applied to coverable code
type T;
}
#[no_coverage]
#[coverage(off)]
fn main() {
#[no_coverage]
//~^ WARN `#[no_coverage]` may only be applied to function definitions
#[coverage(off)]
//~^ WARN `#[coverage]` may only be applied to function definitions
let _ = ();
match () {
#[no_coverage]
//~^ WARN `#[no_coverage]` may only be applied to function definitions
#[coverage(off)]
//~^ WARN `#[coverage]` may only be applied to function definitions
() => (),
}
#[no_coverage]
//~^ WARN `#[no_coverage]` may only be applied to function definitions
#[coverage(off)]
//~^ WARN `#[coverage]` may only be applied to function definitions
return ();
}

View File

@ -1,8 +1,8 @@
warning: `#[no_coverage]` does not propagate into items and must be applied to the contained functions directly
warning: `#[coverage]` does not propagate into items and must be applied to the contained functions directly
--> $DIR/no-coverage.rs:8:1
|
LL | #[no_coverage]
| ^^^^^^^^^^^^^^
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/no-coverage.rs:4:9
@ -10,83 +10,83 @@ note: the lint level is defined here
LL | #![warn(unused_attributes)]
| ^^^^^^^^^^^^^^^^^
warning: `#[no_coverage]` does not propagate into items and must be applied to the contained functions directly
warning: `#[coverage]` does not propagate into items and must be applied to the contained functions directly
--> $DIR/no-coverage.rs:20:1
|
LL | #[no_coverage]
| ^^^^^^^^^^^^^^
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^
warning: `#[no_coverage]` may only be applied to function definitions
warning: `#[coverage]` may only be applied to function definitions
--> $DIR/no-coverage.rs:42:5
|
LL | #[no_coverage]
| ^^^^^^^^^^^^^^
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^
warning: `#[no_coverage]` may only be applied to function definitions
warning: `#[coverage]` may only be applied to function definitions
--> $DIR/no-coverage.rs:47:9
|
LL | #[no_coverage]
| ^^^^^^^^^^^^^^
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^
warning: `#[no_coverage]` may only be applied to function definitions
warning: `#[coverage]` may only be applied to function definitions
--> $DIR/no-coverage.rs:52:5
|
LL | #[no_coverage]
| ^^^^^^^^^^^^^^
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^
error[E0788]: `#[no_coverage]` must be applied to coverable code
error[E0788]: `#[coverage]` must be applied to coverable code
--> $DIR/no-coverage.rs:11:5
|
LL | #[no_coverage]
| ^^^^^^^^^^^^^^
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^
LL | const X: u32;
| ------------- not coverable code
error[E0788]: `#[no_coverage]` must be applied to coverable code
error[E0788]: `#[coverage]` must be applied to coverable code
--> $DIR/no-coverage.rs:14:5
|
LL | #[no_coverage]
| ^^^^^^^^^^^^^^
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^
LL | type T;
| ------- not coverable code
error[E0788]: `#[no_coverage]` must be applied to coverable code
error[E0788]: `#[coverage]` must be applied to coverable code
--> $DIR/no-coverage.rs:25:5
|
LL | #[no_coverage]
| ^^^^^^^^^^^^^^
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^
LL | type T = Self;
| -------------- not coverable code
error[E0788]: `#[no_coverage]` must be applied to coverable code
error[E0788]: `#[coverage]` must be applied to coverable code
--> $DIR/no-coverage.rs:28:5
|
LL | #[no_coverage]
| ^^^^^^^^^^^^^^
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^
LL | type U = impl Trait;
| -------------------- not coverable code
error[E0788]: `#[no_coverage]` must be applied to coverable code
error[E0788]: `#[coverage]` must be applied to coverable code
--> $DIR/no-coverage.rs:33:5
|
LL | #[no_coverage]
| ^^^^^^^^^^^^^^
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^
LL | static X: u32;
| -------------- not coverable code
error[E0788]: `#[no_coverage]` must be applied to coverable code
error[E0788]: `#[coverage]` must be applied to coverable code
--> $DIR/no-coverage.rs:36:5
|
LL | #[no_coverage]
| ^^^^^^^^^^^^^^
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^
LL | type T;
| ------- not coverable code
warning: `#[no_coverage]` does not propagate into items and must be applied to the contained functions directly
warning: `#[coverage]` does not propagate into items and must be applied to the contained functions directly
--> $DIR/no-coverage.rs:5:1
|
LL | #![no_coverage]
| ^^^^^^^^^^^^^^^
LL | #![coverage(off)]
| ^^^^^^^^^^^^^^^^^
error: unconstrained opaque type
--> $DIR/no-coverage.rs:29:14