Skip to content

Commit e82af0b

Browse files
committed
coverage: Migrate unstable options to new flag -Zcoverage-options
Moving these unstable values over to a separate unstable flag has a few benefits: - No need to distinguish stable/unstable values of `-Cinstrument-coverage`. - Multiple options can be enabled/disabled independently. - New behavior can be prototyped behind its own flag, and then enabled by default when ready.
1 parent d780a03 commit e82af0b

16 files changed

+98
-91
lines changed

compiler/rustc_session/src/config.rs

+27-42
Original file line numberDiff line numberDiff line change
@@ -135,30 +135,32 @@ pub enum LtoCli {
135135
/// selected, code structure, and enabled attributes. If errors are encountered,
136136
/// either while compiling or when generating `llvm-cov show` reports, consider
137137
/// lowering the optimization level, including or excluding `-C link-dead-code`,
138-
/// or using `-Zunstable-options -C instrument-coverage=except-unused-functions`
139-
/// or `-Zunstable-options -C instrument-coverage=except-unused-generics`.
140-
///
141-
/// Note that `ExceptUnusedFunctions` means: When `mapgen.rs` generates the
142-
/// coverage map, it will not attempt to generate synthetic functions for unused
143-
/// (and not code-generated) functions (whether they are generic or not). As a
144-
/// result, non-codegenned functions will not be included in the coverage map,
145-
/// and will not appear, as covered or uncovered, in coverage reports.
146-
///
147-
/// `ExceptUnusedGenerics` will add synthetic functions to the coverage map,
148-
/// unless the function has type parameters.
138+
/// or using `-Z coverage-options=no-unused-functions` or
139+
/// `-Z coverage-options=no-unused-generics`.
149140
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
150141
pub enum InstrumentCoverage {
151142
/// `-C instrument-coverage=no` (or `off`, `false` etc.)
152143
No,
153144
/// `-C instrument-coverage` or `-C instrument-coverage=yes`
154145
Yes,
155-
/// Additionally, instrument branches and output branch coverage.
156-
/// `-Zunstable-options -C instrument-coverage=branch`
157-
Branch,
158-
/// `-Zunstable-options -C instrument-coverage=except-unused-generics`
159-
ExceptUnusedGenerics,
160-
/// `-Zunstable-options -C instrument-coverage=except-unused-functions`
161-
ExceptUnusedFunctions,
146+
}
147+
148+
/// Settings for the `-Z coverage-options` flag.
149+
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
150+
pub struct CoverageOptions {
151+
/// Add branch coverage instrumentation (placeholder flag; not yet implemented).
152+
pub branch: bool,
153+
/// Emit coverage mappings for unused functions.
154+
pub unused_functions: bool,
155+
/// When emitting coverage mappings for unused functions, include unused
156+
/// generic functions.
157+
pub unused_generics: bool,
158+
}
159+
160+
impl Default for CoverageOptions {
161+
fn default() -> Self {
162+
Self { branch: false, unused_functions: true, unused_generics: true }
163+
}
162164
}
163165

164166
/// Settings for `-Z instrument-xray` flag.
@@ -2718,24 +2720,6 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
27182720
}
27192721
}
27202722

2721-
// Check for unstable values of `-C instrument-coverage`.
2722-
// This is what prevents them from being used on stable compilers.
2723-
match cg.instrument_coverage {
2724-
// Stable values:
2725-
InstrumentCoverage::Yes | InstrumentCoverage::No => {}
2726-
// Unstable values:
2727-
InstrumentCoverage::Branch
2728-
| InstrumentCoverage::ExceptUnusedFunctions
2729-
| InstrumentCoverage::ExceptUnusedGenerics => {
2730-
if !unstable_opts.unstable_options {
2731-
early_dcx.early_fatal(
2732-
"`-C instrument-coverage=branch` and `-C instrument-coverage=except-*` \
2733-
require `-Z unstable-options`",
2734-
);
2735-
}
2736-
}
2737-
}
2738-
27392723
if cg.instrument_coverage != InstrumentCoverage::No {
27402724
if cg.profile_generate.enabled() || cg.profile_use.is_some() {
27412725
early_dcx.early_fatal(
@@ -3204,12 +3188,12 @@ pub enum WasiExecModel {
32043188
/// how the hash should be calculated when adding a new command-line argument.
32053189
pub(crate) mod dep_tracking {
32063190
use super::{
3207-
BranchProtection, CFGuard, CFProtection, CollapseMacroDebuginfo, CrateType, DebugInfo,
3208-
DebugInfoCompression, ErrorOutputType, FunctionReturn, InliningThreshold,
3209-
InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail, LtoCli,
3210-
NextSolverConfig, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes, Polonius,
3211-
RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind,
3212-
SwitchWithOptPath, SymbolManglingVersion, WasiExecModel,
3191+
BranchProtection, CFGuard, CFProtection, CollapseMacroDebuginfo, CoverageOptions,
3192+
CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FunctionReturn,
3193+
InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail,
3194+
LtoCli, NextSolverConfig, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes,
3195+
Polonius, RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm,
3196+
SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion, WasiExecModel,
32133197
};
32143198
use crate::lint;
32153199
use crate::utils::NativeLib;
@@ -3279,6 +3263,7 @@ pub(crate) mod dep_tracking {
32793263
CodeModel,
32803264
TlsModel,
32813265
InstrumentCoverage,
3266+
CoverageOptions,
32823267
InstrumentXRay,
32833268
CrateType,
32843269
MergeFunctions,

compiler/rustc_session/src/options.rs

+28-16
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,9 @@ mod desc {
395395
pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavorCli::one_of();
396396
pub const parse_optimization_fuel: &str = "crate=integer";
397397
pub const parse_dump_mono_stats: &str = "`markdown` (default) or `json`";
398-
pub const parse_instrument_coverage: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc) or (unstable) one of `branch`, `except-unused-generics`, `except-unused-functions`";
398+
pub const parse_instrument_coverage: &str = parse_bool;
399+
pub const parse_coverage_options: &str =
400+
"one or more of `branch`, `no-unused-functions`, `no-unused-generics` (comma separated)";
399401
pub const parse_instrument_xray: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), or a comma separated list of settings: `always` or `never` (mutually exclusive), `ignore-loops`, `instruction-threshold=N`, `skip-entry`, `skip-exit`";
400402
pub const parse_unpretty: &str = "`string` or `string=string`";
401403
pub const parse_treat_err_as_bug: &str = "either no value or a non-negative number";
@@ -930,19 +932,32 @@ mod parse {
930932

931933
*slot = match v {
932934
"all" => InstrumentCoverage::Yes,
933-
"branch" => InstrumentCoverage::Branch,
934-
"except-unused-generics" | "except_unused_generics" => {
935-
InstrumentCoverage::ExceptUnusedGenerics
936-
}
937-
"except-unused-functions" | "except_unused_functions" => {
938-
InstrumentCoverage::ExceptUnusedFunctions
939-
}
940935
"0" => InstrumentCoverage::No,
941936
_ => return false,
942937
};
943938
true
944939
}
945940

941+
pub(crate) fn parse_coverage_options(slot: &mut CoverageOptions, v: Option<&str>) -> bool {
942+
let Some(v) = v else { return true };
943+
944+
for option in v.split(',') {
945+
let (option, enabled) = match option.strip_prefix("no-") {
946+
Some(without_no) => (without_no, false),
947+
None => (option, true),
948+
};
949+
let slot = match option {
950+
"branch" => &mut slot.branch,
951+
"unused-functions" => &mut slot.unused_functions,
952+
"unused-generics" => &mut slot.unused_generics,
953+
_ => return false,
954+
};
955+
*slot = enabled;
956+
}
957+
958+
true
959+
}
960+
946961
pub(crate) fn parse_instrument_xray(
947962
slot: &mut Option<InstrumentXRay>,
948963
v: Option<&str>,
@@ -1445,14 +1460,9 @@ options! {
14451460
"set the threshold for inlining a function"),
14461461
#[rustc_lint_opt_deny_field_access("use `Session::instrument_coverage` instead of this field")]
14471462
instrument_coverage: InstrumentCoverage = (InstrumentCoverage::No, parse_instrument_coverage, [TRACKED],
1448-
"instrument the generated code to support LLVM source-based code coverage \
1449-
reports (note, the compiler build config must include `profiler = true`); \
1450-
implies `-C symbol-mangling-version=v0`. Optional values are:
1451-
`=no` `=n` `=off` `=false` (default)
1452-
`=yes` `=y` `=on` `=true` (implicit value)
1453-
`=branch` (unstable)
1454-
`=except-unused-generics` (unstable)
1455-
`=except-unused-functions` (unstable)"),
1463+
"instrument the generated code to support LLVM source-based code coverage reports \
1464+
(note, the compiler build config must include `profiler = true`); \
1465+
implies `-C symbol-mangling-version=v0`"),
14561466
link_arg: (/* redirected to link_args */) = ((), parse_string_push, [UNTRACKED],
14571467
"a single extra argument to append to the linker invocation (can be used several times)"),
14581468
link_args: Vec<String> = (Vec::new(), parse_list, [UNTRACKED],
@@ -1574,6 +1584,8 @@ options! {
15741584
"set option to collapse debuginfo for macros"),
15751585
combine_cgu: bool = (false, parse_bool, [TRACKED],
15761586
"combine CGUs into a single one"),
1587+
coverage_options: CoverageOptions = (CoverageOptions::default(), parse_coverage_options, [TRACKED],
1588+
"control details of coverage instrumentation"),
15771589
crate_attr: Vec<String> = (Vec::new(), parse_string_push, [TRACKED],
15781590
"inject the given attribute in the crate"),
15791591
cross_crate_inline_threshold: InliningThreshold = (InliningThreshold::Sometimes(100), parse_inlining_threshold, [TRACKED],

compiler/rustc_session/src/session.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -353,15 +353,15 @@ impl Session {
353353
}
354354

355355
pub fn instrument_coverage_branch(&self) -> bool {
356-
self.opts.cg.instrument_coverage() == InstrumentCoverage::Branch
356+
self.instrument_coverage() && self.opts.unstable_opts.coverage_options.branch
357357
}
358358

359359
pub fn instrument_coverage_except_unused_generics(&self) -> bool {
360-
self.opts.cg.instrument_coverage() == InstrumentCoverage::ExceptUnusedGenerics
360+
self.instrument_coverage() && !self.opts.unstable_opts.coverage_options.unused_generics
361361
}
362362

363363
pub fn instrument_coverage_except_unused_functions(&self) -> bool {
364-
self.opts.cg.instrument_coverage() == InstrumentCoverage::ExceptUnusedFunctions
364+
self.instrument_coverage() && !self.opts.unstable_opts.coverage_options.unused_functions
365365
}
366366

367367
pub fn is_sanitizer_cfi_enabled(&self) -> bool {

src/doc/rustc/src/instrument-coverage.md

+14-8
Original file line numberDiff line numberDiff line change
@@ -346,14 +346,20 @@ $ llvm-cov report \
346346
more fine-grained coverage options are added.
347347
Using this value is currently not recommended.
348348

349-
### Unstable values
350-
351-
- `-Z unstable-options -C instrument-coverage=branch`:
352-
Placeholder for potential branch coverage support in the future.
353-
- `-Z unstable-options -C instrument-coverage=except-unused-generics`:
354-
Instrument all functions except unused generics.
355-
- `-Z unstable-options -C instrument-coverage=except-unused-functions`:
356-
Instrument only used (called) functions and instantiated generic functions.
349+
## `-Z coverage-options=<options>`
350+
351+
This unstable option provides finer control over some aspects of coverage
352+
instrumentation. Pass one or more of the following values, separated by commas.
353+
354+
- `branch` or `no-branch`
355+
- Placeholder for potential branch coverage support in the future.
356+
- `unused-functions` or `no-unused-functions`
357+
- When enabled (default), coverage metadata includes entries for unused functions.
358+
- When disabled, unused functions are not included in coverage metadata.
359+
- `unused-generics` or `no-unused-generics`
360+
- When enabled (default), coverage metadata includes entries for unused generic functions.
361+
- When disabled, unused generic functions are not included in coverage metadata.
362+
- No effect if `no-unused-functions` is also set.
357363

358364
## Other references
359365

tests/coverage/except-unused.default.coverage

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
LL| |
44
LL| |//@ edition: 2021
55
LL| |//@ revisions: default functions generics
6-
LL| |//@ [functions] compile-flags: -Zunstable-options -Cinstrument-coverage=except-unused-functions
7-
LL| |//@ [generics] compile-flags: -Zunstable-options -Cinstrument-coverage=except-unused-generics
6+
LL| |//@ [functions] compile-flags: -Zcoverage-options=no-unused-functions
7+
LL| |//@ [generics] compile-flags: -Zcoverage-options=no-unused-generics
88
LL| |
99
LL| 1|fn used_generic<T>(_x: T) {
1010
LL| 1| println!("used_generic");

tests/coverage/except-unused.functions.coverage

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
LL| |
44
LL| |//@ edition: 2021
55
LL| |//@ revisions: default functions generics
6-
LL| |//@ [functions] compile-flags: -Zunstable-options -Cinstrument-coverage=except-unused-functions
7-
LL| |//@ [generics] compile-flags: -Zunstable-options -Cinstrument-coverage=except-unused-generics
6+
LL| |//@ [functions] compile-flags: -Zcoverage-options=no-unused-functions
7+
LL| |//@ [generics] compile-flags: -Zcoverage-options=no-unused-generics
88
LL| |
99
LL| 1|fn used_generic<T>(_x: T) {
1010
LL| 1| println!("used_generic");

tests/coverage/except-unused.generics.coverage

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
LL| |
44
LL| |//@ edition: 2021
55
LL| |//@ revisions: default functions generics
6-
LL| |//@ [functions] compile-flags: -Zunstable-options -Cinstrument-coverage=except-unused-functions
7-
LL| |//@ [generics] compile-flags: -Zunstable-options -Cinstrument-coverage=except-unused-generics
6+
LL| |//@ [functions] compile-flags: -Zcoverage-options=no-unused-functions
7+
LL| |//@ [generics] compile-flags: -Zcoverage-options=no-unused-generics
88
LL| |
99
LL| 1|fn used_generic<T>(_x: T) {
1010
LL| 1| println!("used_generic");

tests/coverage/except-unused.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44
//@ edition: 2021
55
//@ revisions: default functions generics
6-
//@ [functions] compile-flags: -Zunstable-options -Cinstrument-coverage=except-unused-functions
7-
//@ [generics] compile-flags: -Zunstable-options -Cinstrument-coverage=except-unused-generics
6+
//@ [functions] compile-flags: -Zcoverage-options=no-unused-functions
7+
//@ [generics] compile-flags: -Zcoverage-options=no-unused-generics
88

99
fn used_generic<T>(_x: T) {
1010
println!("used_generic");
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
error: incorrect value `bad-value` for codegen option `instrument-coverage` - either a boolean (`yes`, `no`, `on`, `off`, etc) or (unstable) one of `branch`, `except-unused-generics`, `except-unused-functions` was expected
1+
error: incorrect value `bad-value` for codegen option `instrument-coverage` - one of: `y`, `yes`, `on`, `true`, `n`, `no`, `off` or `false` was expected
22

Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
error: incorrect value `` for codegen option `instrument-coverage` - either a boolean (`yes`, `no`, `on`, `off`, etc) or (unstable) one of `branch`, `except-unused-generics`, `except-unused-functions` was expected
1+
error: incorrect value `` for codegen option `instrument-coverage` - one of: `y`, `yes`, `on`, `true`, `n`, `no`, `off` or `false` was expected
22

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
error: incorrect value `branch,bad` for unstable option `coverage-options` - one or more of `branch`, `no-unused-functions`, `no-unused-generics` (comma separated) was expected
2+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//@ needs-profiler-support
2+
//@ revisions: comma one bad
3+
//@ compile-flags -Cinstrument-coverage
4+
5+
//@ [comma] check-pass
6+
//@ [comma] compile-flags: -Zcoverage-options=branch,no-unused-functions
7+
8+
//@ [one] check-pass
9+
//@ [one] compile-flags: -Zcoverage-options=no-branch
10+
11+
//@ [bad] check-fail
12+
//@ [bad] compile-flags: -Zcoverage-options=branch,bad
13+
14+
fn main() {}

tests/ui/instrument-coverage/unstable.branch.stderr

-2
This file was deleted.

tests/ui/instrument-coverage/unstable.except-unused-functions.stderr

-2
This file was deleted.

tests/ui/instrument-coverage/unstable.except-unused-generics.stderr

-2
This file was deleted.

tests/ui/instrument-coverage/unstable.rs

-6
This file was deleted.

0 commit comments

Comments
 (0)