1
1
use crate :: coverageinfo:: ffi:: { Counter , CounterExpression , ExprKind } ;
2
2
3
- use rustc_data_structures:: fx:: FxIndexSet ;
3
+ use rustc_data_structures:: fx:: { FxHashMap , FxIndexSet } ;
4
4
use rustc_index:: bit_set:: BitSet ;
5
5
use rustc_index:: IndexVec ;
6
6
use rustc_middle:: mir:: coverage:: { CodeRegion , CounterId , CovTerm , ExpressionId , Op } ;
7
7
use rustc_middle:: ty:: Instance ;
8
8
use rustc_middle:: ty:: TyCtxt ;
9
+ use rustc_span:: Symbol ;
9
10
10
11
#[ derive( Clone , Debug , PartialEq ) ]
11
12
pub struct Expression {
@@ -33,7 +34,10 @@ pub struct FunctionCoverage<'tcx> {
33
34
34
35
counters_seen : BitSet < CounterId > ,
35
36
expressions : IndexVec < ExpressionId , Option < Expression > > ,
36
- mappings : Vec < ( CovTerm , CodeRegion ) > ,
37
+
38
+ /// Invariant: Each code region's filename must match the filename key that
39
+ /// it is stored under.
40
+ mappings_per_file : FxHashMap < Symbol , Vec < ( CovTerm , CodeRegion ) > > ,
37
41
}
38
42
39
43
impl < ' tcx > FunctionCoverage < ' tcx > {
@@ -59,7 +63,7 @@ impl<'tcx> FunctionCoverage<'tcx> {
59
63
is_used,
60
64
counters_seen : BitSet :: new_empty ( coverageinfo. num_counters as usize ) ,
61
65
expressions : IndexVec :: from_elem_n ( None , coverageinfo. num_expressions as usize ) ,
62
- mappings : Vec :: new ( ) ,
66
+ mappings_per_file : FxHashMap :: default ( ) ,
63
67
}
64
68
}
65
69
@@ -137,8 +141,14 @@ impl<'tcx> FunctionCoverage<'tcx> {
137
141
}
138
142
139
143
fn add_mappings ( & mut self , kind : CovTerm , code_regions : & [ CodeRegion ] ) {
140
- self . mappings
141
- . extend ( code_regions. iter ( ) . cloned ( ) . map ( move |code_region| ( kind, code_region) ) ) ;
144
+ // There's no need to sort the regions by filename before grouping here,
145
+ // because the result is the same either way.
146
+ for regions_for_file in code_regions. group_by ( |a, b| a. file_name == b. file_name ) {
147
+ let file_name = regions_for_file[ 0 ] . file_name ;
148
+ self . mappings_per_file . entry ( file_name) . or_default ( ) . extend (
149
+ regions_for_file. iter ( ) . cloned ( ) . map ( move |code_region| ( kind, code_region) ) ,
150
+ ) ;
151
+ }
142
152
}
143
153
144
154
pub ( crate ) fn finalize ( & mut self ) {
@@ -149,7 +159,9 @@ impl<'tcx> FunctionCoverage<'tcx> {
149
159
CovTerm :: Expression ( _) => 1 ,
150
160
CovTerm :: Zero => u8:: MAX ,
151
161
} ;
152
- self . mappings . sort_by_key ( |( mapping_kind, _) | mapping_kind_sort_key ( mapping_kind) ) ;
162
+ for mappings in self . mappings_per_file . values_mut ( ) {
163
+ mappings. sort_by_key ( |( mapping_kind, _) | mapping_kind_sort_key ( mapping_kind) ) ;
164
+ }
153
165
}
154
166
155
167
/// Perform some simplifications to make the final coverage mappings
@@ -228,7 +240,8 @@ impl<'tcx> FunctionCoverage<'tcx> {
228
240
// the two vectors should correspond 1:1.
229
241
assert_eq ! ( self . expressions. len( ) , counter_expressions. len( ) ) ;
230
242
231
- let counter_regions = self . mappings . iter ( ) . map ( |( mapping_kind, code_region) | {
243
+ let all_mappings = self . mappings_per_file . values ( ) . flatten ( ) ;
244
+ let counter_regions = all_mappings. map ( |( mapping_kind, code_region) | {
232
245
let counter = Counter :: from_term ( * mapping_kind) ;
233
246
( counter, code_region)
234
247
} ) ;
0 commit comments