@@ -8,7 +8,7 @@ use rustc_span::Span;
88use crate :: coverage:: graph:: { BasicCoverageBlock , CoverageGraph } ;
99use crate :: coverage:: mappings;
1010use crate :: coverage:: spans:: from_mir:: {
11- extract_covspans_and_holes_from_mir, ExtractedCovspans , SpanFromMir ,
11+ extract_covspans_and_holes_from_mir, ExtractedCovspans , Hole , SpanFromMir ,
1212} ;
1313use crate :: coverage:: ExtractedHirInfo ;
1414
@@ -53,39 +53,7 @@ pub(super) fn extract_refined_covspans(
5353 holes. sort_by ( |a, b| compare_spans ( a. span , b. span ) ) ;
5454 holes. dedup_by ( |b, a| a. merge_if_overlapping_or_adjacent ( b) ) ;
5555
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) ;
8957
9058 for mut covspans in buckets {
9159 // Make sure each individual bucket is internally sorted.
@@ -149,6 +117,55 @@ fn split_visible_macro_spans(covspans: &mut Vec<SpanFromMir>) {
149117 covspans. extend ( extra_spans) ;
150118}
151119
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+
152169/// Similar to `.drain(..)`, but stops just before it would remove an item not
153170/// satisfying the predicate.
154171fn drain_front_while < ' a , T > (
0 commit comments