Skip to content

Commit 3a5df48

Browse files
committed
adds feature gating of no_coverage at either crate- or function-level
1 parent 888d0b4 commit 3a5df48

File tree

13 files changed

+142
-63
lines changed

13 files changed

+142
-63
lines changed

compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,19 @@ pub fn expand_deriving_eq(
1616
push: &mut dyn FnMut(Annotatable),
1717
) {
1818
let inline = cx.meta_word(span, sym::inline);
19+
let no_coverage_ident =
20+
rustc_ast::attr::mk_nested_word_item(Ident::new(sym::no_coverage, span));
21+
let no_coverage_feature =
22+
rustc_ast::attr::mk_list_item(Ident::new(sym::feature, span), vec![no_coverage_ident]);
1923
let no_coverage = cx.meta_word(span, sym::no_coverage);
2024
let hidden = rustc_ast::attr::mk_nested_word_item(Ident::new(sym::hidden, span));
2125
let doc = rustc_ast::attr::mk_list_item(Ident::new(sym::doc, span), vec![hidden]);
22-
let attrs = vec![cx.attribute(inline), cx.attribute(no_coverage), cx.attribute(doc)];
26+
let attrs = vec![
27+
cx.attribute(inline),
28+
cx.attribute(no_coverage_feature),
29+
cx.attribute(no_coverage),
30+
cx.attribute(doc),
31+
];
2332
let trait_def = TraitDef {
2433
span,
2534
attributes: Vec::new(),

compiler/rustc_feature/src/active.rs

+4
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,10 @@ declare_features! (
649649
/// Allows `extern "wasm" fn`
650650
(active, wasm_abi, "1.53.0", Some(83788), None),
651651

652+
/// Allows function attribute `#[no_coverage]`, to bypass coverage
653+
/// instrumentation of that function.
654+
(active, no_coverage, "1.53.0", Some(84605), None),
655+
652656
/// Allows trait bounds in `const fn`.
653657
(active, const_fn_trait_bound, "1.53.0", Some(57563), None),
654658

compiler/rustc_feature/src/builtin_attrs.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
264264

265265
// Code generation:
266266
ungated!(inline, AssumedUsed, template!(Word, List: "always|never")),
267-
ungated!(no_coverage, AssumedUsed, template!(Word)),
268267
ungated!(cold, AssumedUsed, template!(Word)),
269268
ungated!(no_builtins, AssumedUsed, template!(Word)),
270269
ungated!(target_feature, AssumedUsed, template!(List: r#"enable = "name""#)),
@@ -274,6 +273,13 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
274273
template!(List: "address, memory, thread"),
275274
experimental!(no_sanitize)
276275
),
276+
ungated!(
277+
// Not exclusively gated at the crate level (though crate-level is
278+
// supported). The feature can alternatively be enabled on individual
279+
// functions.
280+
no_coverage, AssumedUsed,
281+
template!(Word),
282+
),
277283

278284
// FIXME: #14408 assume docs are used since rustdoc looks at them.
279285
ungated!(doc, AssumedUsed, template!(List: "hidden|inline|...", NameValueStr: "string")),

compiler/rustc_typeck/src/collect.rs

+27-1
Original file line numberDiff line numberDiff line change
@@ -2661,6 +2661,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
26612661
let mut inline_span = None;
26622662
let mut link_ordinal_span = None;
26632663
let mut no_sanitize_span = None;
2664+
let mut no_coverage_feature_enabled = false;
2665+
let mut no_coverage_attr = None;
26642666
for attr in attrs.iter() {
26652667
if tcx.sess.check_name(attr, sym::cold) {
26662668
codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD;
@@ -2724,8 +2726,15 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
27242726
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED;
27252727
} else if tcx.sess.check_name(attr, sym::no_mangle) {
27262728
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
2729+
} else if attr.has_name(sym::feature) {
2730+
if let Some(list) = attr.meta_item_list() {
2731+
if list.iter().any(|nested_meta_item| nested_meta_item.has_name(sym::no_coverage)) {
2732+
tcx.sess.mark_attr_used(attr);
2733+
no_coverage_feature_enabled = true;
2734+
}
2735+
}
27272736
} else if tcx.sess.check_name(attr, sym::no_coverage) {
2728-
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE;
2737+
no_coverage_attr = Some(attr);
27292738
} else if tcx.sess.check_name(attr, sym::rustc_std_internal_symbol) {
27302739
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
27312740
} else if tcx.sess.check_name(attr, sym::used) {
@@ -2936,6 +2945,23 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
29362945
}
29372946
}
29382947

2948+
if let Some(no_coverage_attr) = no_coverage_attr {
2949+
if tcx.sess.features_untracked().no_coverage || no_coverage_feature_enabled {
2950+
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_COVERAGE
2951+
} else {
2952+
let mut err = feature_err(
2953+
&tcx.sess.parse_sess,
2954+
sym::no_coverage,
2955+
no_coverage_attr.span,
2956+
"the `#[no_coverage]` attribute is an experimental feature",
2957+
);
2958+
if tcx.sess.parse_sess.unstable_features.is_nightly_build() {
2959+
err.help("or, alternatively, add `#[feature(no_coverage)]` to the function");
2960+
}
2961+
err.emit();
2962+
}
2963+
}
2964+
29392965
codegen_fn_attrs.inline = attrs.iter().fold(InlineAttr::None, |ia, attr| {
29402966
if !attr.has_name(sym::inline) {
29412967
return ia;

library/core/src/cmp.rs

+1
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ pub trait Eq: PartialEq<Self> {
274274
//
275275
// This should never be implemented by hand.
276276
#[doc(hidden)]
277+
#[cfg_attr(not(bootstrap), feature(no_coverage))]
277278
#[cfg_attr(not(bootstrap), no_coverage)]
278279
#[inline]
279280
#[stable(feature = "rust1", since = "1.0.0")]

src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.issue-84561.txt

-34
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
1| |// Enables `no_coverage` on the entire crate
2+
2| |#![feature(no_coverage)]
3+
3| |
4+
4| |#[no_coverage]
5+
5| |fn do_not_add_coverage_1() {
6+
6| | println!("called but not covered");
7+
7| |}
8+
8| |
9+
9| |#[no_coverage]
10+
10| |fn do_not_add_coverage_2() {
11+
11| | println!("called but not covered");
12+
12| |}
13+
13| |
14+
14| 1|fn main() {
15+
15| 1| do_not_add_coverage_1();
16+
16| 1| do_not_add_coverage_2();
17+
17| 1|}
18+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
1| |// Enables `no_coverage` on individual functions
2+
2| |
3+
3| |#[feature(no_coverage)]
4+
4| |#[no_coverage]
5+
5| |fn do_not_add_coverage_1() {
6+
6| | println!("called but not covered");
7+
7| |}
8+
8| |
9+
9| |#[no_coverage]
10+
10| |#[feature(no_coverage)]
11+
11| |fn do_not_add_coverage_2() {
12+
12| | println!("called but not covered");
13+
13| |}
14+
14| |
15+
15| 1|fn main() {
16+
16| 1| do_not_add_coverage_1();
17+
17| 1| do_not_add_coverage_2();
18+
18| 1|}
19+

src/test/run-make-fulldeps/coverage/issue-84561.rs

-26
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Enables `no_coverage` on the entire crate
2+
#![feature(no_coverage)]
3+
4+
#[no_coverage]
5+
fn do_not_add_coverage_1() {
6+
println!("called but not covered");
7+
}
8+
9+
#[no_coverage]
10+
fn do_not_add_coverage_2() {
11+
println!("called but not covered");
12+
}
13+
14+
fn main() {
15+
do_not_add_coverage_1();
16+
do_not_add_coverage_2();
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Enables `no_coverage` on individual functions
2+
3+
#[feature(no_coverage)]
4+
#[no_coverage]
5+
fn do_not_add_coverage_1() {
6+
println!("called but not covered");
7+
}
8+
9+
#[no_coverage]
10+
#[feature(no_coverage)]
11+
fn do_not_add_coverage_2() {
12+
println!("called but not covered");
13+
}
14+
15+
fn main() {
16+
do_not_add_coverage_1();
17+
do_not_add_coverage_2();
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![crate_type = "lib"]
2+
3+
#[no_coverage]
4+
#[feature(no_coverage)] // does not have to be enabled before `#[no_coverage]`
5+
fn no_coverage_is_enabled_on_this_function() {}
6+
7+
#[no_coverage] //~ ERROR the `#[no_coverage]` attribute is an experimental feature
8+
fn requires_feature_no_coverage() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
error[E0658]: the `#[no_coverage]` attribute is an experimental feature
2+
--> $DIR/feature-gate-no_coverage.rs:7:1
3+
|
4+
LL | #[no_coverage]
5+
| ^^^^^^^^^^^^^^
6+
|
7+
= note: see issue #84605 <https://github.com/rust-lang/rust/issues/84605> for more information
8+
= help: add `#![feature(no_coverage)]` to the crate attributes to enable
9+
= help: or, alternatively, add `#[feature(no_coverage)]` to the function
10+
11+
error: aborting due to previous error
12+
13+
For more information about this error, try `rustc --explain E0658`.

0 commit comments

Comments
 (0)