Rework no_coverage to coverage(off)

This commit is contained in:
Andy Caldwell 2023-08-09 15:57:16 +01:00
parent de4cba3a98
commit 8e03371fc3
No known key found for this signature in database
GPG Key ID: D4204541AC1D228D
27 changed files with 183 additions and 158 deletions

View File

@ -34,7 +34,7 @@ pub fn expand_deriving_eq(
attributes: thin_vec![ attributes: thin_vec![
cx.attr_word(sym::inline, span), cx.attr_word(sym::inline, span),
cx.attr_nested_word(sym::doc, sym::hidden, 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, fieldless_variants_strategy: FieldlessVariantsStrategy::Unify,
combine_substructure: combine_substructure(Box::new(|a, b, c| { 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( let expn_id = ext_cx.resolver.expansion_for_ast_pass(
DUMMY_SP, DUMMY_SP,
AstPass::TestHarness, AstPass::TestHarness,
&[sym::test, sym::rustc_attrs, sym::no_coverage], &[sym::test, sym::rustc_attrs, sym::coverage],
None, None,
); );
let def_site = DUMMY_SP.with_def_site_ctxt(expn_id.to_expn_id()); 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] // #[rustc_main]
let main_attr = ecx.attr_word(sym::rustc_main, sp); let main_attr = ecx.attr_word(sym::rustc_main, sp);
// #[no_coverage] // #[coverage(off)]
let no_coverage_attr = ecx.attr_word(sym::no_coverage, sp); let coverage_attr = ecx.attr_nested_word(sym::coverage, sym::off, sp);
// pub fn main() { ... } // pub fn main() { ... }
let main_ret_ty = ecx.ty(sp, ast::TyKind::Tup(ThinVec::new())); 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 { let main = P(ast::Item {
ident: main_id, ident: main_id,
attrs: thin_vec![main_attr, no_coverage_attr], attrs: thin_vec![main_attr, coverage_attr],
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
kind: main, kind: main,
vis: ast::Visibility { span: sp, kind: ast::VisibilityKind::Public, tokens: None }, vis: ast::Visibility { span: sp, kind: ast::VisibilityKind::Public, tokens: None },

View File

@ -317,10 +317,10 @@ fn add_unused_functions(cx: &CodegenCx<'_, '_>) {
{ {
let codegen_fn_attrs = tcx.codegen_fn_attrs(non_codegenned_def_id); 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. // dead code stub for it.
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NO_COVERAGE) { 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; 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_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_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 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::errors;
use crate::target_features::from_target_feature; 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 { fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage {
use rustc_middle::mir::mono::Linkage::*; use rustc_middle::mir::mono::Linkage::*;
@ -128,7 +131,21 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
.emit(); .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 scopy.
}
Some(_) | None => {
tcx.sess.emit_err(ExpectedCoverageSymbol { span: attr.span });
}
}
}
sym::rustc_std_internal_symbol => { sym::rustc_std_internal_symbol => {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::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, pub kind: &'a str,
} }
#[derive(Diagnostic)]
#[diag(codegen_ssa_expected_coverage_symbol)]
pub struct ExpectedCoverageSymbol {
#[primary_span]
pub span: Span,
}
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(codegen_ssa_expected_used_symbol)] #[diag(codegen_ssa_expected_used_symbol)]
pub struct ExpectedUsedSymbol { 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. 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 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: Example of erroneous code:
```compile_fail,E0788 ```compile_fail,E0788
#[no_coverage] #[coverage(off)]
struct Foo; struct Foo;
#[no_coverage] #[coverage(on)]
const FOO: Foo = Foo; const FOO: Foo = Foo;
``` ```
`#[no_coverage]` tells the compiler to not generate coverage instrumentation for `#[coverage(off)]` tells the compiler to not generate coverage instrumentation
a piece of code when the `-C instrument-coverage` flag is passed. Things like for a piece of code when the `-C instrument-coverage` flag is passed. Things
structs and consts are not coverable code, and thus cannot do anything with this like structs and consts are not coverable code, and thus cannot do anything
attribute. with this attribute.
If you wish to apply this attribute to all methods in an impl or module, 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 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), (active, const_trait_impl, "1.42.0", Some(67792), None),
/// Allows the `?` operator in const contexts. /// Allows the `?` operator in const contexts.
(active, const_try, "1.56.0", Some(74935), None), (active, const_try, "1.56.0", Some(74935), None),
/// Allows function attribute `#[coverage(on/off)]`, to control coverage
/// instrumentation of that function.
(active, coverage, "1.53.0", Some(84605), None),
/// Allows non-builtin attributes in inner attribute position. /// Allows non-builtin attributes in inner attribute position.
(active, custom_inner_attributes, "1.30.0", Some(54726), None), (active, custom_inner_attributes, "1.30.0", Some(54726), None),
/// Allows custom test frameworks with `#![test_runner]` and `#[test_case]`. /// 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), (active, never_type_fallback, "1.41.0", Some(65992), None),
/// Allows `#![no_core]`. /// Allows `#![no_core]`.
(active, no_core, "1.3.0", Some(29639), None), (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. /// Allows the use of `no_sanitize` attribute.
(active, no_sanitize, "1.42.0", Some(39699), None), (active, no_sanitize, "1.42.0", Some(39699), None),
/// Allows using the `non_exhaustive_omitted_patterns` lint. /// 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, template!(List: "address, kcfi, memory, thread"), DuplicatesOk,
experimental!(no_sanitize) 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!( ungated!(
doc, Normal, template!(List: "hidden|inline|...", NameValueStr: "string"), DuplicatesOk doc, Normal, template!(List: "hidden|inline|...", NameValueStr: "string"), DuplicatesOk

View File

@ -87,7 +87,7 @@ bitflags! {
/// #[cmse_nonsecure_entry]: with a TrustZone-M extension, declare a /// #[cmse_nonsecure_entry]: with a TrustZone-M extension, declare a
/// function as an entry function from Non-Secure code. /// function as an entry function from Non-Secure code.
const CMSE_NONSECURE_ENTRY = 1 << 14; 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 /// the MIR `InstrumentCoverage` pass and not added to the coverage map
/// during codegen. /// during codegen.
const NO_COVERAGE = 1 << 15; const NO_COVERAGE = 1 << 15;

View File

@ -113,6 +113,19 @@ passes_continue_labeled_block =
.label = labeled blocks cannot be `continue`'d .label = labeled blocks cannot be `continue`'d
.block_label = labeled block the `continue` points to .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 = passes_dead_codes =
{ $multiple -> { $multiple ->
*[true] multiple {$descr}s are *[true] multiple {$descr}s are
@ -497,19 +510,6 @@ passes_naked_functions_operands =
passes_naked_tracked_caller = passes_naked_tracked_caller =
cannot use `#[track_caller]` with `#[naked]` 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 = passes_no_link =
attribute should be applied to an `extern crate` item attribute should be applied to an `extern crate` item
.label = not an `extern crate` item .label = not an `extern crate` item

View File

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

View File

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

View File

@ -573,6 +573,7 @@ symbols! {
cosf32, cosf32,
cosf64, cosf64,
count, count,
coverage,
cr, cr,
crate_id, crate_id,
crate_in_paths, crate_in_paths,
@ -1037,7 +1038,6 @@ symbols! {
no, no,
no_builtins, no_builtins,
no_core, no_core,
no_coverage,
no_crate_inject, no_crate_inject,
no_debug, no_debug,
no_default_passes, no_default_passes,
@ -1068,6 +1068,7 @@ symbols! {
note, note,
object_safe_for_dispatch, object_safe_for_dispatch,
of, of,
off,
offset, offset,
offset_of, offset_of,
omit_gdb_pretty_printer_section, omit_gdb_pretty_printer_section,

View File

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

View File

@ -110,6 +110,8 @@
// //
// Library features: // Library features:
// tidy-alphabetical-start // tidy-alphabetical-start
#![cfg_attr(bootstrap, feature(no_coverage))] // rust-lang/rust#84605
#![cfg_attr(not(bootstrap), feature(coverage))] // rust-lang/rust#84605
#![feature(char_indices_offset)] #![feature(char_indices_offset)]
#![feature(const_align_of_val)] #![feature(const_align_of_val)]
#![feature(const_align_of_val_raw)] #![feature(const_align_of_val_raw)]
@ -235,7 +237,6 @@
#![feature(negative_impls)] #![feature(negative_impls)]
#![feature(never_type)] #![feature(never_type)]
#![feature(no_core)] #![feature(no_core)]
#![feature(no_coverage)] // rust-lang/rust#84605
#![feature(platform_intrinsics)] #![feature(platform_intrinsics)]
#![feature(prelude_import)] #![feature(prelude_import)]
#![feature(repr_simd)] #![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 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 [`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 ## Interpreting reports

View File

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

View File

@ -239,7 +239,7 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[
template!(List: "address, kcfi, memory, thread"), DuplicatesOk, template!(List: "address, kcfi, memory, thread"), DuplicatesOk,
experimental!(no_sanitize) 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!( ungated!(
doc, Normal, template!(List: "hidden|inline|...", NameValueStr: "string"), DuplicatesOk doc, Normal, template!(List: "hidden|inline|...", NameValueStr: "string"), DuplicatesOk

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,12 @@
error[E0658]: the `#[coverage]` attribute is an experimental feature
--> $DIR/feature-gate-coverage.rs:9:1
|
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^
|
= note: see issue #84605 <https://github.com/rust-lang/rust/issues/84605> for more information
= help: add `#![feature(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,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(extern_types)]
#![feature(no_coverage)] #![feature(coverage)]
#![feature(impl_trait_in_assoc_type)] #![feature(impl_trait_in_assoc_type)]
#![warn(unused_attributes)] #![warn(unused_attributes)]
#![no_coverage] #![coverage(off)]
//~^ WARN: `#[no_coverage]` does not propagate into items and must be applied to the contained functions directly //~^ WARN: `#[coverage]` does not propagate into items and must be applied to the contained functions directly
#[no_coverage] #[coverage(off)]
//~^ WARN: `#[no_coverage]` does not propagate into items and must be applied to the contained functions directly //~^ WARN: `#[coverage]` does not propagate into items and must be applied to the contained functions directly
trait Trait { 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; 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 T;
type U; type U;
} }
#[no_coverage] #[coverage(off)]
//~^ WARN: `#[no_coverage]` does not propagate into items and must be applied to the contained functions directly //~^ WARN: `#[coverage]` does not propagate into items and must be applied to the contained functions directly
impl Trait for () { impl Trait for () {
const X: u32 = 0; 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; 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 type U = impl Trait; //~ ERROR unconstrained opaque type
} }
extern "C" { 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; 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; type T;
} }
#[no_coverage] #[coverage(off)]
fn main() { fn main() {
#[no_coverage] #[coverage(off)]
//~^ WARN `#[no_coverage]` may only be applied to function definitions //~^ WARN `#[coverage]` may only be applied to function definitions
let _ = (); let _ = ();
match () { match () {
#[no_coverage] #[coverage(off)]
//~^ WARN `#[no_coverage]` may only be applied to function definitions //~^ WARN `#[coverage]` may only be applied to function definitions
() => (), () => (),
} }
#[no_coverage] #[coverage(off)]
//~^ WARN `#[no_coverage]` may only be applied to function definitions //~^ WARN `#[coverage]` may only be applied to function definitions
return (); 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 --> $DIR/no-coverage.rs:8:1
| |
LL | #[no_coverage] LL | #[coverage(off)]
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^
| |
note: the lint level is defined here note: the lint level is defined here
--> $DIR/no-coverage.rs:4:9 --> $DIR/no-coverage.rs:4:9
@ -10,83 +10,83 @@ note: the lint level is defined here
LL | #![warn(unused_attributes)] 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 --> $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 --> $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 --> $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 --> $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 --> $DIR/no-coverage.rs:11:5
| |
LL | #[no_coverage] LL | #[coverage(off)]
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^
LL | const X: u32; LL | const X: u32;
| ------------- not coverable code | ------------- 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 --> $DIR/no-coverage.rs:14:5
| |
LL | #[no_coverage] LL | #[coverage(off)]
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^
LL | type T; LL | type T;
| ------- not coverable code | ------- 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 --> $DIR/no-coverage.rs:25:5
| |
LL | #[no_coverage] LL | #[coverage(off)]
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^
LL | type T = Self; LL | type T = Self;
| -------------- not coverable code | -------------- 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 --> $DIR/no-coverage.rs:28:5
| |
LL | #[no_coverage] LL | #[coverage(off)]
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^
LL | type U = impl Trait; LL | type U = impl Trait;
| -------------------- not coverable code | -------------------- 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 --> $DIR/no-coverage.rs:33:5
| |
LL | #[no_coverage] LL | #[coverage(off)]
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^
LL | static X: u32; LL | static X: u32;
| -------------- not coverable code | -------------- 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 --> $DIR/no-coverage.rs:36:5
| |
LL | #[no_coverage] LL | #[coverage(off)]
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^
LL | type T; LL | type T;
| ------- not coverable code | ------- 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 --> $DIR/no-coverage.rs:5:1
| |
LL | #![no_coverage] LL | #![coverage(off)]
| ^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^
error: unconstrained opaque type error: unconstrained opaque type
--> $DIR/no-coverage.rs:29:14 --> $DIR/no-coverage.rs:29:14