@@ -9,7 +9,7 @@ mod tests;
99
1010use self :: counters:: { CounterIncrementSite , CoverageCounters } ;
1111use self :: graph:: { BasicCoverageBlock , CoverageGraph } ;
12- use self :: spans:: { BcbMapping , BcbMappingKind , CoverageSpans } ;
12+ use self :: spans:: { BcbBranchArm , BcbMapping , BcbMappingKind , CoverageSpans } ;
1313
1414use crate :: MirPass ;
1515
@@ -83,10 +83,10 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir:
8383 // and all `Expression` dependencies (operands) are also generated, for any other
8484 // `BasicCoverageBlock`s not already associated with a coverage span.
8585 let bcb_has_coverage_spans = |bcb| coverage_spans. bcb_has_coverage_spans ( bcb) ;
86- let coverage_counters =
86+ let mut coverage_counters =
8787 CoverageCounters :: make_bcb_counters ( & basic_coverage_blocks, bcb_has_coverage_spans) ;
8888
89- let mappings = create_mappings ( tcx, & hir_info, & coverage_spans, & coverage_counters) ;
89+ let mappings = create_mappings ( tcx, & hir_info, & coverage_spans, & mut coverage_counters) ;
9090 if mappings. is_empty ( ) {
9191 // No spans could be converted into valid mappings, so skip this function.
9292 debug ! ( "no spans could be converted into valid mappings; skipping" ) ;
@@ -117,7 +117,7 @@ fn create_mappings<'tcx>(
117117 tcx : TyCtxt < ' tcx > ,
118118 hir_info : & ExtractedHirInfo ,
119119 coverage_spans : & CoverageSpans ,
120- coverage_counters : & CoverageCounters ,
120+ coverage_counters : & mut CoverageCounters ,
121121) -> Vec < Mapping > {
122122 let source_map = tcx. sess . source_map ( ) ;
123123 let body_span = hir_info. body_span ;
@@ -136,20 +136,46 @@ fn create_mappings<'tcx>(
136136 . as_term ( )
137137 } ;
138138
139- coverage_spans
140- . all_bcb_mappings ( )
141- . filter_map ( |& BcbMapping { kind : bcb_mapping_kind, span } | {
139+ let mut mappings = vec ! [ ] ;
140+
141+ mappings. extend ( coverage_spans. all_bcb_mappings ( ) . filter_map (
142+ |& BcbMapping { kind : bcb_mapping_kind, span } | {
142143 let kind = match bcb_mapping_kind {
143144 BcbMappingKind :: Code ( bcb) => MappingKind :: Code ( term_for_bcb ( bcb) ) ,
144- BcbMappingKind :: Branch { true_bcb, false_bcb } => MappingKind :: Branch {
145- true_term : term_for_bcb ( true_bcb) ,
146- false_term : term_for_bcb ( false_bcb) ,
147- } ,
148145 } ;
149146 let code_region = make_code_region ( source_map, file_name, span, body_span) ?;
150147 Some ( Mapping { kind, code_region } )
151- } )
152- . collect :: < Vec < _ > > ( )
148+ } ,
149+ ) ) ;
150+
151+ for arm_list in & coverage_spans. branch_arm_lists {
152+ let mut arms_rev = arm_list. iter ( ) . rev ( ) ;
153+
154+ let mut rest_counter = {
155+ // The last arm's span is ignored, because its BCB is only used as the
156+ // false branch of the second-last arm; it's not a branch of its own.
157+ let Some ( & BcbBranchArm { span : _, bcb } ) = arms_rev. next ( ) else { continue } ;
158+ coverage_counters. bcb_counter ( bcb) . expect ( "all relevant BCBs have counters" )
159+ } ;
160+
161+ for & BcbBranchArm { span, bcb } in arms_rev {
162+ let true_counter =
163+ coverage_counters. bcb_counter ( bcb) . expect ( "all relevant BCBs have counters" ) ;
164+ let kind = MappingKind :: Branch {
165+ true_term : true_counter. as_term ( ) ,
166+ false_term : rest_counter. as_term ( ) ,
167+ } ;
168+
169+ if let Some ( code_region) = make_code_region ( source_map, file_name, span, body_span) {
170+ mappings. push ( Mapping { kind, code_region } ) ;
171+ }
172+
173+ // FIXME: Avoid creating an unused expression on the last iteration.
174+ rest_counter = coverage_counters. make_expression ( true_counter, Op :: Add , rest_counter) ;
175+ }
176+ }
177+
178+ mappings
153179}
154180
155181/// For each BCB node or BCB edge that has an associated coverage counter,
0 commit comments