@@ -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,7 @@ 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
+ let buckets = divide_spans_into_buckets ( covspans, & holes) ;
89
57
90
58
for mut covspans in buckets {
91
59
// Make sure each individual bucket is internally sorted.
@@ -149,6 +117,55 @@ fn split_visible_macro_spans(covspans: &mut Vec<SpanFromMir>) {
149
117
covspans. extend ( extra_spans) ;
150
118
}
151
119
120
+ /// Uses the holes to divide the given covspans into buckets, such that:
121
+ /// - No span in any hole overlaps a bucket (truncating the spans if necessary).
122
+ /// - The spans in each bucket are strictly after all spans in previous buckets,
123
+ /// and strictly before all spans in subsequent buckets.
124
+ ///
125
+ /// The resulting buckets are sorted relative to each other, but might not be
126
+ /// internally sorted.
127
+ #[ instrument( level = "debug" ) ]
128
+ fn divide_spans_into_buckets ( input_covspans : Vec < Covspan > , holes : & [ Hole ] ) -> Vec < Vec < Covspan > > {
129
+ debug_assert ! ( input_covspans. is_sorted_by( |a, b| compare_spans( a. span, b. span) . is_le( ) ) ) ;
130
+ debug_assert ! ( holes. is_sorted_by( |a, b| compare_spans( a. span, b. span) . is_le( ) ) ) ;
131
+
132
+ // Now we're ready to start carving holes out of the initial coverage spans,
133
+ // and grouping them in buckets separated by the holes.
134
+
135
+ let mut input_covspans = VecDeque :: from ( input_covspans) ;
136
+ let mut fragments = vec ! [ ] ;
137
+
138
+ // For each hole:
139
+ // - Identify the spans that are entirely or partly before the hole.
140
+ // - Put those spans in a corresponding bucket, truncated to the start of the hole.
141
+ // - If one of those spans also extends after the hole, put the rest of it
142
+ // in a "fragments" vector that is processed by the next hole.
143
+ let mut buckets = ( 0 ..holes. len ( ) ) . map ( |_| vec ! [ ] ) . collect :: < Vec < _ > > ( ) ;
144
+ for ( hole, bucket) in holes. iter ( ) . zip ( & mut buckets) {
145
+ let fragments_from_prev = std:: mem:: take ( & mut fragments) ;
146
+
147
+ // Only inspect spans that precede or overlap this hole,
148
+ // leaving the rest to be inspected by later holes.
149
+ // (This relies on the spans and holes both being sorted.)
150
+ let relevant_input_covspans =
151
+ drain_front_while ( & mut input_covspans, |c| c. span . lo ( ) < hole. span . hi ( ) ) ;
152
+
153
+ for covspan in fragments_from_prev. into_iter ( ) . chain ( relevant_input_covspans) {
154
+ let ( before, after) = covspan. split_around_hole_span ( hole. span ) ;
155
+ bucket. extend ( before) ;
156
+ fragments. extend ( after) ;
157
+ }
158
+ }
159
+
160
+ // After finding the spans before each hole, any remaining fragments/spans
161
+ // form their own final bucket, after the final hole.
162
+ // (If there were no holes, this will just be all of the initial spans.)
163
+ fragments. extend ( input_covspans) ;
164
+ buckets. push ( fragments) ;
165
+
166
+ buckets
167
+ }
168
+
152
169
/// Similar to `.drain(..)`, but stops just before it would remove an item not
153
170
/// satisfying the predicate.
154
171
fn drain_front_while < ' a , T > (
0 commit comments