@@ -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