@@ -9,7 +9,7 @@ mod tests;
9
9
10
10
use self :: counters:: { CounterIncrementSite , CoverageCounters } ;
11
11
use self :: graph:: { BasicCoverageBlock , CoverageGraph } ;
12
- use self :: spans:: { BcbMapping , BcbMappingKind , CoverageSpans } ;
12
+ use self :: spans:: { BcbBranchArm , BcbMapping , BcbMappingKind , CoverageSpans } ;
13
13
14
14
use crate :: MirPass ;
15
15
@@ -83,10 +83,10 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir:
83
83
// and all `Expression` dependencies (operands) are also generated, for any other
84
84
// `BasicCoverageBlock`s not already associated with a coverage span.
85
85
let bcb_has_coverage_spans = |bcb| coverage_spans. bcb_has_coverage_spans ( bcb) ;
86
- let coverage_counters =
86
+ let mut coverage_counters =
87
87
CoverageCounters :: make_bcb_counters ( & basic_coverage_blocks, bcb_has_coverage_spans) ;
88
88
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) ;
90
90
if mappings. is_empty ( ) {
91
91
// No spans could be converted into valid mappings, so skip this function.
92
92
debug ! ( "no spans could be converted into valid mappings; skipping" ) ;
@@ -117,7 +117,7 @@ fn create_mappings<'tcx>(
117
117
tcx : TyCtxt < ' tcx > ,
118
118
hir_info : & ExtractedHirInfo ,
119
119
coverage_spans : & CoverageSpans ,
120
- coverage_counters : & CoverageCounters ,
120
+ coverage_counters : & mut CoverageCounters ,
121
121
) -> Vec < Mapping > {
122
122
let source_map = tcx. sess . source_map ( ) ;
123
123
let body_span = hir_info. body_span ;
@@ -136,20 +136,46 @@ fn create_mappings<'tcx>(
136
136
. as_term ( )
137
137
} ;
138
138
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 } | {
142
143
let kind = match bcb_mapping_kind {
143
144
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
- } ,
148
145
} ;
149
146
let code_region = make_code_region ( source_map, file_name, span, body_span) ?;
150
147
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
153
179
}
154
180
155
181
/// For each BCB node or BCB edge that has an associated coverage counter,
0 commit comments