@@ -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,8 @@ 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+ // Split the covspans into separate buckets that don't overlap any holes.
57+ let buckets = divide_spans_into_buckets ( covspans, & holes) ;
8958
9059 for mut covspans in buckets {
9160 // Make sure each individual bucket is internally sorted.
@@ -149,6 +118,55 @@ fn split_visible_macro_spans(covspans: &mut Vec<SpanFromMir>) {
149118 covspans. extend ( extra_spans) ;
150119}
151120
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+
152170/// Similar to `.drain(..)`, but stops just before it would remove an item not
153171/// satisfying the predicate.
154172fn drain_front_while < ' a , T > (
0 commit comments