@@ -22,7 +22,7 @@ use rustc_middle::mir::{
22
22
TerminatorKind ,
23
23
} ;
24
24
use rustc_middle:: ty:: TyCtxt ;
25
- use rustc_span:: def_id:: DefId ;
25
+ use rustc_span:: def_id:: { DefId , LocalDefId } ;
26
26
use rustc_span:: source_map:: SourceMap ;
27
27
use rustc_span:: { ExpnKind , SourceFile , Span , Symbol } ;
28
28
@@ -45,18 +45,13 @@ impl<'tcx> MirPass<'tcx> for InstrumentCoverage {
45
45
46
46
let def_id = mir_source. def_id ( ) . expect_local ( ) ;
47
47
48
- // Only instrument functions, methods, and closures (not constants since they are evaluated
49
- // at compile time by Miri).
50
- // FIXME(#73156): Handle source code coverage in const eval, but note, if and when const
51
- // expressions get coverage spans, we will probably have to "carve out" space for const
52
- // expressions from coverage spans in enclosing MIR's, like we do for closures. (That might
53
- // be tricky if const expressions have no corresponding statements in the enclosing MIR.
54
- // Closures are carved out by their initial `Assign` statement.)
55
- if !tcx. def_kind ( def_id) . is_fn_like ( ) {
56
- trace ! ( "InstrumentCoverage skipped for {def_id:?} (not an fn-like)" ) ;
48
+ if !is_eligible_for_coverage ( tcx, def_id) {
49
+ trace ! ( "InstrumentCoverage skipped for {def_id:?} (not eligible)" ) ;
57
50
return ;
58
51
}
59
52
53
+ // An otherwise-eligible function is still skipped if its start block
54
+ // is known to be unreachable.
60
55
match mir_body. basic_blocks [ mir:: START_BLOCK ] . terminator ( ) . kind {
61
56
TerminatorKind :: Unreachable => {
62
57
trace ! ( "InstrumentCoverage skipped for unreachable `START_BLOCK`" ) ;
@@ -65,10 +60,6 @@ impl<'tcx> MirPass<'tcx> for InstrumentCoverage {
65
60
_ => { }
66
61
}
67
62
68
- if tcx. codegen_fn_attrs ( def_id) . flags . contains ( CodegenFnAttrFlags :: NO_COVERAGE ) {
69
- return ;
70
- }
71
-
72
63
trace ! ( "InstrumentCoverage starting for {def_id:?}" ) ;
73
64
Instrumentor :: new ( tcx, mir_body) . inject_counters ( ) ;
74
65
trace ! ( "InstrumentCoverage done for {def_id:?}" ) ;
@@ -317,6 +308,26 @@ fn make_code_region(
317
308
}
318
309
}
319
310
311
+ fn is_eligible_for_coverage ( tcx : TyCtxt < ' _ > , def_id : LocalDefId ) -> bool {
312
+ // Only instrument functions, methods, and closures (not constants since they are evaluated
313
+ // at compile time by Miri).
314
+ // FIXME(#73156): Handle source code coverage in const eval, but note, if and when const
315
+ // expressions get coverage spans, we will probably have to "carve out" space for const
316
+ // expressions from coverage spans in enclosing MIR's, like we do for closures. (That might
317
+ // be tricky if const expressions have no corresponding statements in the enclosing MIR.
318
+ // Closures are carved out by their initial `Assign` statement.)
319
+ if !tcx. def_kind ( def_id) . is_fn_like ( ) {
320
+ trace ! ( "InstrumentCoverage skipped for {def_id:?} (not an fn-like)" ) ;
321
+ return false ;
322
+ }
323
+
324
+ if tcx. codegen_fn_attrs ( def_id) . flags . contains ( CodegenFnAttrFlags :: NO_COVERAGE ) {
325
+ return false ;
326
+ }
327
+
328
+ true
329
+ }
330
+
320
331
fn fn_sig_and_body (
321
332
tcx : TyCtxt < ' _ > ,
322
333
def_id : DefId ,
0 commit comments