@@ -2,7 +2,7 @@ use std::assert_matches::assert_matches;
22use std:: collections:: hash_map:: Entry ;
33
44use rustc_data_structures:: fx:: FxHashMap ;
5- use rustc_middle:: mir:: coverage:: { BlockMarkerId , BranchSpan , CoverageKind } ;
5+ use rustc_middle:: mir:: coverage:: { BlockMarkerId , BranchSpan , CoverageInfoHi , CoverageKind } ;
66use rustc_middle:: mir:: { self , BasicBlock , SourceInfo , UnOp } ;
77use rustc_middle:: thir:: { ExprId , ExprKind , Pat , Thir } ;
88use rustc_middle:: ty:: TyCtxt ;
@@ -13,16 +13,25 @@ use crate::build::{Builder, CFG};
1313
1414mod mcdc;
1515
16- pub ( crate ) struct BranchInfoBuilder {
16+ /// Collects coverage-related information during MIR building, to eventually be
17+ /// turned into a function's [`CoverageInfoHi`] when MIR building is complete.
18+ pub ( crate ) struct CoverageInfoBuilder {
1719 /// Maps condition expressions to their enclosing `!`, for better instrumentation.
1820 nots : FxHashMap < ExprId , NotInfo > ,
1921
2022 markers : BlockMarkerGen ,
21- branch_spans : Vec < BranchSpan > ,
2223
24+ /// Present if branch coverage is enabled.
25+ branch_info : Option < BranchInfo > ,
26+ /// Present if MC/DC coverage is enabled.
2327 mcdc_info : Option < MCDCInfoBuilder > ,
2428}
2529
30+ #[ derive( Default ) ]
31+ struct BranchInfo {
32+ branch_spans : Vec < BranchSpan > ,
33+ }
34+
2635#[ derive( Clone , Copy ) ]
2736struct NotInfo {
2837 /// When visiting the associated expression as a branch condition, treat this
@@ -62,20 +71,20 @@ impl BlockMarkerGen {
6271 }
6372}
6473
65- impl BranchInfoBuilder {
66- /// Creates a new branch info builder, but only if branch coverage instrumentation
74+ impl CoverageInfoBuilder {
75+ /// Creates a new coverage info builder, but only if coverage instrumentation
6776 /// is enabled and `def_id` represents a function that is eligible for coverage.
6877 pub ( crate ) fn new_if_enabled ( tcx : TyCtxt < ' _ > , def_id : LocalDefId ) -> Option < Self > {
69- if tcx. sess . instrument_coverage_branch ( ) && tcx. is_eligible_for_coverage ( def_id) {
70- Some ( Self {
71- nots : FxHashMap :: default ( ) ,
72- markers : BlockMarkerGen :: default ( ) ,
73- branch_spans : vec ! [ ] ,
74- mcdc_info : tcx. sess . instrument_coverage_mcdc ( ) . then ( MCDCInfoBuilder :: new) ,
75- } )
76- } else {
77- None
78+ if !tcx. sess . instrument_coverage ( ) || !tcx. is_eligible_for_coverage ( def_id) {
79+ return None ;
7880 }
81+
82+ Some ( Self {
83+ nots : FxHashMap :: default ( ) ,
84+ markers : BlockMarkerGen :: default ( ) ,
85+ branch_info : tcx. sess . instrument_coverage_branch ( ) . then ( BranchInfo :: default) ,
86+ mcdc_info : tcx. sess . instrument_coverage_mcdc ( ) . then ( MCDCInfoBuilder :: new) ,
87+ } )
7988 }
8089
8190 /// Unary `!` expressions inside an `if` condition are lowered by lowering
@@ -88,6 +97,12 @@ impl BranchInfoBuilder {
8897 pub ( crate ) fn visit_unary_not ( & mut self , thir : & Thir < ' _ > , unary_not : ExprId ) {
8998 assert_matches ! ( thir[ unary_not] . kind, ExprKind :: Unary { op: UnOp :: Not , .. } ) ;
9099
100+ // The information collected by this visitor is only needed when branch
101+ // coverage or higher is enabled.
102+ if self . branch_info . is_none ( ) {
103+ return ;
104+ }
105+
91106 self . visit_with_not_info (
92107 thir,
93108 unary_not,
@@ -137,40 +152,40 @@ impl BranchInfoBuilder {
137152 false_block,
138153 inject_block_marker,
139154 ) ;
140- } else {
141- let true_marker = self . markers . inject_block_marker ( cfg, source_info, true_block) ;
142- let false_marker = self . markers . inject_block_marker ( cfg, source_info, false_block) ;
143-
144- self . branch_spans . push ( BranchSpan {
145- span : source_info. span ,
146- true_marker,
147- false_marker,
148- } ) ;
155+ return ;
149156 }
157+
158+ // Bail out if branch coverage is not enabled.
159+ let Some ( branch_info) = self . branch_info . as_mut ( ) else { return } ;
160+
161+ let true_marker = self . markers . inject_block_marker ( cfg, source_info, true_block) ;
162+ let false_marker = self . markers . inject_block_marker ( cfg, source_info, false_block) ;
163+
164+ branch_info. branch_spans . push ( BranchSpan {
165+ span : source_info. span ,
166+ true_marker,
167+ false_marker,
168+ } ) ;
150169 }
151170
152- pub ( crate ) fn into_done ( self ) -> Option < Box < mir:: coverage:: BranchInfo > > {
153- let Self {
154- nots : _,
155- markers : BlockMarkerGen { num_block_markers } ,
156- branch_spans,
157- mcdc_info,
158- } = self ;
171+ pub ( crate ) fn into_done ( self ) -> Box < CoverageInfoHi > {
172+ let Self { nots : _, markers : BlockMarkerGen { num_block_markers } , branch_info, mcdc_info } =
173+ self ;
159174
160- if num_block_markers == 0 {
161- assert ! ( branch_spans. is_empty( ) ) ;
162- return None ;
163- }
175+ let branch_spans =
176+ branch_info. map ( |branch_info| branch_info. branch_spans ) . unwrap_or_default ( ) ;
164177
165178 let ( mcdc_decision_spans, mcdc_branch_spans) =
166179 mcdc_info. map ( MCDCInfoBuilder :: into_done) . unwrap_or_default ( ) ;
167180
168- Some ( Box :: new ( mir:: coverage:: BranchInfo {
181+ // For simplicity, always return an info struct (without Option), even
182+ // if there's nothing interesting in it.
183+ Box :: new ( CoverageInfoHi {
169184 num_block_markers,
170185 branch_spans,
171186 mcdc_branch_spans,
172187 mcdc_decision_spans,
173- } ) )
188+ } )
174189 }
175190}
176191
@@ -184,7 +199,7 @@ impl<'tcx> Builder<'_, 'tcx> {
184199 block : & mut BasicBlock ,
185200 ) {
186201 // Bail out if condition coverage is not enabled for this function.
187- let Some ( branch_info ) = self . coverage_branch_info . as_mut ( ) else { return } ;
202+ let Some ( coverage_info ) = self . coverage_info . as_mut ( ) else { return } ;
188203 if !self . tcx . sess . instrument_coverage_condition ( ) {
189204 return ;
190205 } ;
@@ -224,7 +239,7 @@ impl<'tcx> Builder<'_, 'tcx> {
224239 ) ;
225240
226241 // Separate path for handling branches when MC/DC is enabled.
227- branch_info . register_two_way_branch (
242+ coverage_info . register_two_way_branch (
228243 self . tcx ,
229244 & mut self . cfg ,
230245 source_info,
@@ -247,12 +262,12 @@ impl<'tcx> Builder<'_, 'tcx> {
247262 mut then_block : BasicBlock ,
248263 mut else_block : BasicBlock ,
249264 ) {
250- // Bail out if branch coverage is not enabled for this function.
251- let Some ( branch_info ) = self . coverage_branch_info . as_mut ( ) else { return } ;
265+ // Bail out if coverage is not enabled for this function.
266+ let Some ( coverage_info ) = self . coverage_info . as_mut ( ) else { return } ;
252267
253268 // If this condition expression is nested within one or more `!` expressions,
254269 // replace it with the enclosing `!` collected by `visit_unary_not`.
255- if let Some ( & NotInfo { enclosing_not, is_flipped } ) = branch_info . nots . get ( & expr_id) {
270+ if let Some ( & NotInfo { enclosing_not, is_flipped } ) = coverage_info . nots . get ( & expr_id) {
256271 expr_id = enclosing_not;
257272 if is_flipped {
258273 std:: mem:: swap ( & mut then_block, & mut else_block) ;
@@ -261,7 +276,7 @@ impl<'tcx> Builder<'_, 'tcx> {
261276
262277 let source_info = SourceInfo { span : self . thir [ expr_id] . span , scope : self . source_scope } ;
263278
264- branch_info . register_two_way_branch (
279+ coverage_info . register_two_way_branch (
265280 self . tcx ,
266281 & mut self . cfg ,
267282 source_info,
@@ -280,13 +295,11 @@ impl<'tcx> Builder<'_, 'tcx> {
280295 true_block : BasicBlock ,
281296 false_block : BasicBlock ,
282297 ) {
283- // Bail out if branch coverage is not enabled for this function.
284- let Some ( branch_info) = self . coverage_branch_info . as_mut ( ) else { return } ;
285-
286- // FIXME(#124144) This may need special handling when MC/DC is enabled.
298+ // Bail out if coverage is not enabled for this function.
299+ let Some ( coverage_info) = self . coverage_info . as_mut ( ) else { return } ;
287300
288301 let source_info = SourceInfo { span : pattern. span , scope : self . source_scope } ;
289- branch_info . register_two_way_branch (
302+ coverage_info . register_two_way_branch (
290303 self . tcx ,
291304 & mut self . cfg ,
292305 source_info,
0 commit comments