11use crate :: coverageinfo:: ffi:: { Counter , CounterExpression , ExprKind } ;
22
3- use rustc_data_structures:: fx:: FxIndexSet ;
3+ use rustc_data_structures:: fx:: { FxHashMap , FxIndexSet } ;
44use rustc_index:: bit_set:: BitSet ;
55use rustc_index:: IndexVec ;
66use rustc_middle:: mir:: coverage:: { CodeRegion , CounterId , CovTerm , ExpressionId , Op } ;
77use rustc_middle:: ty:: Instance ;
88use rustc_middle:: ty:: TyCtxt ;
9+ use rustc_span:: Symbol ;
910
1011#[ derive( Clone , Debug , PartialEq ) ]
1112pub struct Expression {
@@ -33,7 +34,10 @@ pub struct FunctionCoverage<'tcx> {
3334
3435 counters_seen : BitSet < CounterId > ,
3536 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 ) > > ,
3741}
3842
3943impl < ' tcx > FunctionCoverage < ' tcx > {
@@ -59,7 +63,7 @@ impl<'tcx> FunctionCoverage<'tcx> {
5963 is_used,
6064 counters_seen : BitSet :: new_empty ( coverageinfo. num_counters as usize ) ,
6165 expressions : IndexVec :: from_elem_n ( None , coverageinfo. num_expressions as usize ) ,
62- mappings : Vec :: new ( ) ,
66+ mappings_per_file : FxHashMap :: default ( ) ,
6367 }
6468 }
6569
@@ -137,8 +141,14 @@ impl<'tcx> FunctionCoverage<'tcx> {
137141 }
138142
139143 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+ }
142152 }
143153
144154 pub ( crate ) fn finalize ( & mut self ) {
@@ -149,7 +159,9 @@ impl<'tcx> FunctionCoverage<'tcx> {
149159 CovTerm :: Expression ( _) => 1 ,
150160 CovTerm :: Zero => u8:: MAX ,
151161 } ;
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+ }
153165 }
154166
155167 /// Perform some simplifications to make the final coverage mappings
@@ -228,7 +240,8 @@ impl<'tcx> FunctionCoverage<'tcx> {
228240 // the two vectors should correspond 1:1.
229241 assert_eq ! ( self . expressions. len( ) , counter_expressions. len( ) ) ;
230242
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) | {
232245 let counter = Counter :: from_term ( * mapping_kind) ;
233246 ( counter, code_region)
234247 } ) ;
0 commit comments