@@ -8,7 +8,7 @@ use rustc_span::Span;
8
8
use crate :: coverage:: graph:: { BasicCoverageBlock , CoverageGraph } ;
9
9
use crate :: coverage:: mappings;
10
10
use crate :: coverage:: spans:: from_mir:: {
11
- extract_covspans_and_holes_from_mir, ExtractedCovspans , SpanFromMir ,
11
+ extract_covspans_and_holes_from_mir, ExtractedCovspans , Hole , SpanFromMir ,
12
12
} ;
13
13
use crate :: coverage:: ExtractedHirInfo ;
14
14
@@ -53,39 +53,8 @@ pub(super) fn extract_refined_covspans(
53
53
holes. sort_by ( |a, b| compare_spans ( a. span , b. span ) ) ;
54
54
holes. dedup_by ( |b, a| a. merge_if_overlapping_or_adjacent ( b) ) ;
55
55
56
- // Now we're ready to start carving holes out of the initial coverage spans,
57
- // and grouping them in buckets separated by the holes.
58
-
59
- let mut input_covspans = VecDeque :: from ( covspans) ;
60
- let mut fragments = vec ! [ ] ;
61
-
62
- // For each hole:
63
- // - Identify the spans that are entirely or partly before the hole.
64
- // - Put those spans in a corresponding bucket, truncated to the start of the hole.
65
- // - If one of those spans also extends after the hole, put the rest of it
66
- // in a "fragments" vector that is processed by the next hole.
67
- let mut buckets = ( 0 ..holes. len ( ) ) . map ( |_| vec ! [ ] ) . collect :: < Vec < _ > > ( ) ;
68
- for ( hole, bucket) in holes. iter ( ) . zip ( & mut buckets) {
69
- let fragments_from_prev = std:: mem:: take ( & mut fragments) ;
70
-
71
- // Only inspect spans that precede or overlap this hole,
72
- // leaving the rest to be inspected by later holes.
73
- // (This relies on the spans and holes both being sorted.)
74
- let relevant_input_covspans =
75
- drain_front_while ( & mut input_covspans, |c| c. span . lo ( ) < hole. span . hi ( ) ) ;
76
-
77
- for covspan in fragments_from_prev. into_iter ( ) . chain ( relevant_input_covspans) {
78
- let ( before, after) = covspan. split_around_hole_span ( hole. span ) ;
79
- bucket. extend ( before) ;
80
- fragments. extend ( after) ;
81
- }
82
- }
83
-
84
- // After finding the spans before each hole, any remaining fragments/spans
85
- // form their own final bucket, after the final hole.
86
- // (If there were no holes, this will just be all of the initial spans.)
87
- fragments. extend ( input_covspans) ;
88
- buckets. push ( fragments) ;
56
+ // Split the covspans into separate buckets that don't overlap any holes.
57
+ let buckets = divide_spans_into_buckets ( covspans, & holes) ;
89
58
90
59
for mut covspans in buckets {
91
60
// Make sure each individual bucket is internally sorted.
@@ -149,6 +118,55 @@ fn split_visible_macro_spans(covspans: &mut Vec<SpanFromMir>) {
149
118
covspans. extend ( extra_spans) ;
150
119
}
151
120
121
+ /// Uses the holes to divide the given covspans into buckets, such that:
122
+ /// - No span in any hole overlaps a bucket (truncating the spans if necessary).
123
+ /// - The spans in each bucket are strictly after all spans in previous buckets,
124
+ /// and strictly before all spans in subsequent buckets.
125
+ ///
126
+ /// The resulting buckets are sorted relative to each other, but might not be
127
+ /// internally sorted.
128
+ #[ instrument( level = "debug" ) ]
129
+ fn divide_spans_into_buckets ( input_covspans : Vec < Covspan > , holes : & [ Hole ] ) -> Vec < Vec < Covspan > > {
130
+ debug_assert ! ( input_covspans. is_sorted_by( |a, b| compare_spans( a. span, b. span) . is_le( ) ) ) ;
131
+ debug_assert ! ( holes. is_sorted_by( |a, b| compare_spans( a. span, b. span) . is_le( ) ) ) ;
132
+
133
+ // Now we're ready to start carving holes out of the initial coverage spans,
134
+ // and grouping them in buckets separated by the holes.
135
+
136
+ let mut input_covspans = VecDeque :: from ( input_covspans) ;
137
+ let mut fragments = vec ! [ ] ;
138
+
139
+ // For each hole:
140
+ // - Identify the spans that are entirely or partly before the hole.
141
+ // - Put those spans in a corresponding bucket, truncated to the start of the hole.
142
+ // - If one of those spans also extends after the hole, put the rest of it
143
+ // in a "fragments" vector that is processed by the next hole.
144
+ let mut buckets = ( 0 ..holes. len ( ) ) . map ( |_| vec ! [ ] ) . collect :: < Vec < _ > > ( ) ;
145
+ for ( hole, bucket) in holes. iter ( ) . zip ( & mut buckets) {
146
+ let fragments_from_prev = std:: mem:: take ( & mut fragments) ;
147
+
148
+ // Only inspect spans that precede or overlap this hole,
149
+ // leaving the rest to be inspected by later holes.
150
+ // (This relies on the spans and holes both being sorted.)
151
+ let relevant_input_covspans =
152
+ drain_front_while ( & mut input_covspans, |c| c. span . lo ( ) < hole. span . hi ( ) ) ;
153
+
154
+ for covspan in fragments_from_prev. into_iter ( ) . chain ( relevant_input_covspans) {
155
+ let ( before, after) = covspan. split_around_hole_span ( hole. span ) ;
156
+ bucket. extend ( before) ;
157
+ fragments. extend ( after) ;
158
+ }
159
+ }
160
+
161
+ // After finding the spans before each hole, any remaining fragments/spans
162
+ // form their own final bucket, after the final hole.
163
+ // (If there were no holes, this will just be all of the initial spans.)
164
+ fragments. extend ( input_covspans) ;
165
+ buckets. push ( fragments) ;
166
+
167
+ buckets
168
+ }
169
+
152
170
/// Similar to `.drain(..)`, but stops just before it would remove an item not
153
171
/// satisfying the predicate.
154
172
fn drain_front_while < ' a , T > (
0 commit comments