Skip to content

Commit c728bf3

Browse files
committed
Auto merge of #114656 - bossmc:rework-no-coverage-attr, r=oli-obk
Rework `no_coverage` to `coverage(off)` As discussed at the tail of #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.
2 parents 8142a31 + 0ca6c38 commit c728bf3

File tree

38 files changed

+253
-213
lines changed

38 files changed

+253
-213
lines changed

Diff for: compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ pub fn expand_deriving_eq(
3434
attributes: thin_vec![
3535
cx.attr_word(sym::inline, span),
3636
cx.attr_nested_word(sym::doc, sym::hidden, span),
37-
cx.attr_word(sym::no_coverage, span)
37+
cx.attr_nested_word(sym::coverage, sym::off, span)
3838
],
3939
fieldless_variants_strategy: FieldlessVariantsStrategy::Unify,
4040
combine_substructure: combine_substructure(Box::new(|a, b, c| {

Diff for: compiler/rustc_builtin_macros/src/test_harness.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ fn generate_test_harness(
254254
let expn_id = ext_cx.resolver.expansion_for_ast_pass(
255255
DUMMY_SP,
256256
AstPass::TestHarness,
257-
&[sym::test, sym::rustc_attrs, sym::no_coverage],
257+
&[sym::test, sym::rustc_attrs, sym::coverage_attribute],
258258
None,
259259
);
260260
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> {
335335

336336
// #[rustc_main]
337337
let main_attr = ecx.attr_word(sym::rustc_main, sp);
338-
// #[no_coverage]
339-
let no_coverage_attr = ecx.attr_word(sym::no_coverage, sp);
338+
// #[coverage(off)]
339+
let coverage_attr = ecx.attr_nested_word(sym::coverage, sym::off, sp);
340340

341341
// pub fn main() { ... }
342342
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> {
366366

367367
let main = P(ast::Item {
368368
ident: main_id,
369-
attrs: thin_vec![main_attr, no_coverage_attr],
369+
attrs: thin_vec![main_attr, coverage_attr],
370370
id: ast::DUMMY_NODE_ID,
371371
kind: main,
372372
vis: ast::Visibility { span: sp, kind: ast::VisibilityKind::Public, tokens: None },

Diff for: compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -330,10 +330,10 @@ fn add_unused_functions(cx: &CodegenCx<'_, '_>) {
330330
{
331331
let codegen_fn_attrs = tcx.codegen_fn_attrs(non_codegenned_def_id);
332332

333-
// If a function is marked `#[no_coverage]`, then skip generating a
333+
// If a function is marked `#[coverage(off)]`, then skip generating a
334334
// dead code stub for it.
335335
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NO_COVERAGE) {
336-
debug!("skipping unused fn marked #[no_coverage]: {:?}", non_codegenned_def_id);
336+
debug!("skipping unused fn marked #[coverage(off)]: {:?}", non_codegenned_def_id);
337337
continue;
338338
}
339339

Diff for: compiler/rustc_codegen_ssa/messages.ftl

+2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ codegen_ssa_erroneous_constant = erroneous constant encountered
2323
2424
codegen_ssa_error_creating_remark_dir = failed to create remark directory: {$error}
2525
26+
codegen_ssa_expected_coverage_symbol = expected `coverage(off)` or `coverage(on)`
27+
2628
codegen_ssa_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
2729
2830
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

Diff for: compiler/rustc_codegen_ssa/src/codegen_attrs.rs

+19-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ use rustc_target::spec::{abi, SanitizerSet};
1616

1717
use crate::errors;
1818
use crate::target_features::from_target_feature;
19-
use crate::{errors::ExpectedUsedSymbol, target_features::check_target_feature_trait_unsafe};
19+
use crate::{
20+
errors::{ExpectedCoverageSymbol, ExpectedUsedSymbol},
21+
target_features::check_target_feature_trait_unsafe,
22+
};
2023

2124
fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage {
2225
use rustc_middle::mir::mono::Linkage::*;
@@ -128,7 +131,21 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
128131
.emit();
129132
}
130133
}
131-
sym::no_coverage => codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE,
134+
sym::coverage => {
135+
let inner = attr.meta_item_list();
136+
match inner.as_deref() {
137+
Some([item]) if item.has_name(sym::off) => {
138+
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE;
139+
}
140+
Some([item]) if item.has_name(sym::on) => {
141+
// Allow #[coverage(on)] for being explicit, maybe also in future to enable
142+
// coverage on a smaller scope within an excluded larger scope.
143+
}
144+
Some(_) | None => {
145+
tcx.sess.emit_err(ExpectedCoverageSymbol { span: attr.span });
146+
}
147+
}
148+
}
132149
sym::rustc_std_internal_symbol => {
133150
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL
134151
}

Diff for: compiler/rustc_codegen_ssa/src/errors.rs

+7
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,13 @@ pub struct UnknownArchiveKind<'a> {
561561
pub kind: &'a str,
562562
}
563563

564+
#[derive(Diagnostic)]
565+
#[diag(codegen_ssa_expected_coverage_symbol)]
566+
pub struct ExpectedCoverageSymbol {
567+
#[primary_span]
568+
pub span: Span,
569+
}
570+
564571
#[derive(Diagnostic)]
565572
#[diag(codegen_ssa_expected_used_symbol)]
566573
pub struct ExpectedUsedSymbol {

Diff for: compiler/rustc_error_codes/src/error_codes/E0788.md

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
A `#[no_coverage]` attribute was applied to something which does not show up
1+
A `#[coverage]` attribute was applied to something which does not show up
22
in code coverage, or is too granular to be excluded from the coverage report.
33

44
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.
99
Example of erroneous code:
1010

1111
```compile_fail,E0788
12-
#[no_coverage]
12+
#[coverage(off)]
1313
struct Foo;
1414
15-
#[no_coverage]
15+
#[coverage(on)]
1616
const FOO: Foo = Foo;
1717
```
1818

19-
`#[no_coverage]` tells the compiler to not generate coverage instrumentation for
20-
a piece of code when the `-C instrument-coverage` flag is passed. Things like
21-
structs and consts are not coverable code, and thus cannot do anything with this
22-
attribute.
19+
`#[coverage(off)]` tells the compiler to not generate coverage instrumentation
20+
for a piece of code when the `-C instrument-coverage` flag is passed. Things
21+
like structs and consts are not coverable code, and thus cannot do anything
22+
with this attribute.
2323

2424
If you wish to apply this attribute to all methods in an impl or module,
2525
manually annotate each method; it is not possible to annotate the entire impl
26-
with a `#[no_coverage]` attribute.
26+
with a `#[coverage]` attribute.

Diff for: compiler/rustc_feature/src/active.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,9 @@ declare_features! (
398398
(active, const_trait_impl, "1.42.0", Some(67792), None),
399399
/// Allows the `?` operator in const contexts.
400400
(active, const_try, "1.56.0", Some(74935), None),
401+
/// Allows function attribute `#[coverage(on/off)]`, to control coverage
402+
/// instrumentation of that function.
403+
(active, coverage_attribute, "CURRENT_RUSTC_VERSION", Some(84605), None),
401404
/// Allows non-builtin attributes in inner attribute position.
402405
(active, custom_inner_attributes, "1.30.0", Some(54726), None),
403406
/// Allows custom test frameworks with `#![test_runner]` and `#[test_case]`.
@@ -509,9 +512,6 @@ declare_features! (
509512
(active, never_type_fallback, "1.41.0", Some(65992), None),
510513
/// Allows `#![no_core]`.
511514
(active, no_core, "1.3.0", Some(29639), None),
512-
/// Allows function attribute `#[no_coverage]`, to bypass coverage
513-
/// instrumentation of that function.
514-
(active, no_coverage, "1.53.0", Some(84605), None),
515515
/// Allows the use of `no_sanitize` attribute.
516516
(active, no_sanitize, "1.42.0", Some(39699), None),
517517
/// Allows using the `non_exhaustive_omitted_patterns` lint.

Diff for: compiler/rustc_feature/src/builtin_attrs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
395395
template!(List: "address, kcfi, memory, thread"), DuplicatesOk,
396396
experimental!(no_sanitize)
397397
),
398-
gated!(no_coverage, Normal, template!(Word), WarnFollowing, experimental!(no_coverage)),
398+
gated!(coverage, Normal, template!(Word, List: "on|off"), WarnFollowing, coverage_attribute, experimental!(coverage)),
399399

400400
ungated!(
401401
doc, Normal, template!(List: "hidden|inline|...", NameValueStr: "string"), DuplicatesOk

Diff for: compiler/rustc_feature/src/removed.rs

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

Diff for: compiler/rustc_middle/src/middle/codegen_fn_attrs.rs

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

Diff for: compiler/rustc_passes/messages.ftl

+13-13
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,19 @@ passes_continue_labeled_block =
109109
.label = labeled blocks cannot be `continue`'d
110110
.block_label = labeled block the `continue` points to
111111
112+
passes_coverage_fn_defn =
113+
`#[coverage]` may only be applied to function definitions
114+
115+
passes_coverage_ignored_function_prototype =
116+
`#[coverage]` is ignored on function prototypes
117+
118+
passes_coverage_not_coverable =
119+
`#[coverage]` must be applied to coverable code
120+
.label = not coverable code
121+
122+
passes_coverage_propagate =
123+
`#[coverage]` does not propagate into items and must be applied to the contained functions directly
124+
112125
passes_dead_codes =
113126
{ $multiple ->
114127
*[true] multiple {$descr}s are
@@ -499,19 +512,6 @@ passes_naked_functions_operands =
499512
passes_naked_tracked_caller =
500513
cannot use `#[track_caller]` with `#[naked]`
501514
502-
passes_no_coverage_fn_defn =
503-
`#[no_coverage]` may only be applied to function definitions
504-
505-
passes_no_coverage_ignored_function_prototype =
506-
`#[no_coverage]` is ignored on function prototypes
507-
508-
passes_no_coverage_not_coverable =
509-
`#[no_coverage]` must be applied to coverable code
510-
.label = not coverable code
511-
512-
passes_no_coverage_propagate =
513-
`#[no_coverage]` does not propagate into items and must be applied to the contained functions directly
514-
515515
passes_no_link =
516516
attribute should be applied to an `extern crate` item
517517
.label = not an `extern crate` item

Diff for: compiler/rustc_passes/src/check_attr.rs

+8-14
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ impl CheckAttrVisitor<'_> {
107107
match attr.name_or_empty() {
108108
sym::do_not_recommend => self.check_do_not_recommend(attr.span, target),
109109
sym::inline => self.check_inline(hir_id, attr, span, target),
110-
sym::no_coverage => self.check_no_coverage(hir_id, attr, span, target),
110+
sym::coverage => self.check_coverage(hir_id, attr, span, target),
111111
sym::non_exhaustive => self.check_non_exhaustive(hir_id, attr, span, target),
112112
sym::marker => self.check_marker(hir_id, attr, span, target),
113113
sym::target_feature => self.check_target_feature(hir_id, attr, span, target),
@@ -327,16 +327,10 @@ impl CheckAttrVisitor<'_> {
327327
}
328328
}
329329

330-
/// Checks if a `#[no_coverage]` is applied directly to a function
331-
fn check_no_coverage(
332-
&self,
333-
hir_id: HirId,
334-
attr: &Attribute,
335-
span: Span,
336-
target: Target,
337-
) -> bool {
330+
/// Checks if a `#[coverage]` is applied directly to a function
331+
fn check_coverage(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool {
338332
match target {
339-
// no_coverage on function is fine
333+
// #[coverage] on function is fine
340334
Target::Fn
341335
| Target::Closure
342336
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
@@ -347,7 +341,7 @@ impl CheckAttrVisitor<'_> {
347341
UNUSED_ATTRIBUTES,
348342
hir_id,
349343
attr.span,
350-
errors::IgnoredNoCoverageFnProto,
344+
errors::IgnoredCoverageFnProto,
351345
);
352346
true
353347
}
@@ -357,7 +351,7 @@ impl CheckAttrVisitor<'_> {
357351
UNUSED_ATTRIBUTES,
358352
hir_id,
359353
attr.span,
360-
errors::IgnoredNoCoveragePropagate,
354+
errors::IgnoredCoveragePropagate,
361355
);
362356
true
363357
}
@@ -367,13 +361,13 @@ impl CheckAttrVisitor<'_> {
367361
UNUSED_ATTRIBUTES,
368362
hir_id,
369363
attr.span,
370-
errors::IgnoredNoCoverageFnDefn,
364+
errors::IgnoredCoverageFnDefn,
371365
);
372366
true
373367
}
374368

375369
_ => {
376-
self.tcx.sess.emit_err(errors::IgnoredNoCoverageNotCoverable {
370+
self.tcx.sess.emit_err(errors::IgnoredCoverageNotCoverable {
377371
attr_span: attr.span,
378372
defn_span: span,
379373
});

Diff for: compiler/rustc_passes/src/errors.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -64,20 +64,20 @@ pub struct InlineNotFnOrClosure {
6464
}
6565

6666
#[derive(LintDiagnostic)]
67-
#[diag(passes_no_coverage_ignored_function_prototype)]
68-
pub struct IgnoredNoCoverageFnProto;
67+
#[diag(passes_coverage_ignored_function_prototype)]
68+
pub struct IgnoredCoverageFnProto;
6969

7070
#[derive(LintDiagnostic)]
71-
#[diag(passes_no_coverage_propagate)]
72-
pub struct IgnoredNoCoveragePropagate;
71+
#[diag(passes_coverage_propagate)]
72+
pub struct IgnoredCoveragePropagate;
7373

7474
#[derive(LintDiagnostic)]
75-
#[diag(passes_no_coverage_fn_defn)]
76-
pub struct IgnoredNoCoverageFnDefn;
75+
#[diag(passes_coverage_fn_defn)]
76+
pub struct IgnoredCoverageFnDefn;
7777

7878
#[derive(Diagnostic)]
79-
#[diag(passes_no_coverage_not_coverable, code = "E0788")]
80-
pub struct IgnoredNoCoverageNotCoverable {
79+
#[diag(passes_coverage_not_coverable, code = "E0788")]
80+
pub struct IgnoredCoverageNotCoverable {
8181
#[primary_span]
8282
pub attr_span: Span,
8383
#[label]

Diff for: compiler/rustc_span/src/symbol.rs

+3
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,8 @@ symbols! {
574574
cosf32,
575575
cosf64,
576576
count,
577+
coverage,
578+
coverage_attribute,
577579
cr,
578580
crate_id,
579581
crate_in_paths,
@@ -1069,6 +1071,7 @@ symbols! {
10691071
note,
10701072
object_safe_for_dispatch,
10711073
of,
1074+
off,
10721075
offset,
10731076
offset_of,
10741077
omit_gdb_pretty_printer_section,

Diff for: library/core/src/cmp.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,8 @@ pub trait Eq: PartialEq<Self> {
289289
//
290290
// This should never be implemented by hand.
291291
#[doc(hidden)]
292-
#[no_coverage] // rust-lang/rust#84605
292+
#[cfg_attr(bootstrap, no_coverage)] // rust-lang/rust#84605
293+
#[cfg_attr(not(bootstrap), coverage(off))] //
293294
#[inline]
294295
#[stable(feature = "rust1", since = "1.0.0")]
295296
fn assert_receiver_is_total_eq(&self) {}
@@ -298,7 +299,9 @@ pub trait Eq: PartialEq<Self> {
298299
/// Derive macro generating an impl of the trait [`Eq`].
299300
#[rustc_builtin_macro]
300301
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
301-
#[allow_internal_unstable(core_intrinsics, derive_eq, structural_match, no_coverage)]
302+
#[allow_internal_unstable(core_intrinsics, derive_eq, structural_match)]
303+
#[cfg_attr(bootstrap, allow_internal_unstable(no_coverage))]
304+
#[cfg_attr(not(bootstrap), allow_internal_unstable(coverage_attribute))]
302305
pub macro Eq($item:item) {
303306
/* compiler built-in */
304307
}

Diff for: library/core/src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@
110110
//
111111
// Library features:
112112
// tidy-alphabetical-start
113+
#![cfg_attr(bootstrap, feature(no_coverage))] // rust-lang/rust#84605
114+
#![cfg_attr(not(bootstrap), feature(coverage_attribute))] // rust-lang/rust#84605
113115
#![feature(char_indices_offset)]
114116
#![feature(const_align_of_val)]
115117
#![feature(const_align_of_val_raw)]
@@ -235,7 +237,6 @@
235237
#![feature(negative_impls)]
236238
#![feature(never_type)]
237239
#![feature(no_core)]
238-
#![feature(no_coverage)] // rust-lang/rust#84605
239240
#![feature(platform_intrinsics)]
240241
#![feature(prelude_import)]
241242
#![feature(repr_simd)]

Diff for: src/doc/rustc/src/instrument-coverage.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -173,9 +173,9 @@ Some of the more notable options in this example include:
173173
[`llvm-cov report`]: https://llvm.org/docs/CommandGuide/llvm-cov.html#llvm-cov-report
174174
[`llvm-cov show`]: https://llvm.org/docs/CommandGuide/llvm-cov.html#llvm-cov-show
175175

176-
> **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)]`).
176+
> **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)]`).
177177
178-
[`no_coverage` attribute]: ../unstable-book/language-features/no-coverage.html
178+
[`coverage` attribute]: ../unstable-book/language-features/coverage.html
179179

180180
## Interpreting reports
181181

0 commit comments

Comments
 (0)