@@ -28,11 +28,15 @@ pub(super) fn extract_refined_covspans(
2828 let ExtractedCovspans { mut covspans, mut holes } =
2929 extract_covspans_and_holes_from_mir ( mir_body, hir_info, basic_coverage_blocks) ;
3030
31+ // First, perform the passes that need macro information.
3132 covspans. sort_by ( |a, b| basic_coverage_blocks. cmp_in_dominator_order ( a. bcb , b. bcb ) ) ;
3233 remove_unwanted_macro_spans ( & mut covspans) ;
3334 split_visible_macro_spans ( & mut covspans) ;
3435
35- let compare_covspans = |a : & SpanFromMir , b : & SpanFromMir | {
36+ // We no longer need the extra information in `SpanFromMir`, so convert to `Covspan`.
37+ let mut covspans = covspans. into_iter ( ) . map ( SpanFromMir :: into_covspan) . collect :: < Vec < _ > > ( ) ;
38+
39+ let compare_covspans = |a : & Covspan , b : & Covspan | {
3640 compare_spans ( a. span , b. span )
3741 // After deduplication, we want to keep only the most-dominated BCB.
3842 . then_with ( || basic_coverage_blocks. cmp_in_dominator_order ( a. bcb , b. bcb ) . reverse ( ) )
@@ -53,7 +57,7 @@ pub(super) fn extract_refined_covspans(
5357 // and grouping them in buckets separated by the holes.
5458
5559 let mut input_covspans = VecDeque :: from ( covspans) ;
56- let mut fragments: Vec < SpanFromMir > = vec ! [ ] ;
60+ let mut fragments = vec ! [ ] ;
5761
5862 // For each hole:
5963 // - Identify the spans that are entirely or partly before the hole.
@@ -88,7 +92,7 @@ pub(super) fn extract_refined_covspans(
8892 covspans. sort_by ( compare_covspans) ;
8993
9094 let covspans = refine_sorted_spans ( covspans) ;
91- code_mappings. extend ( covspans. into_iter ( ) . map ( |RefinedCovspan { span, bcb } | {
95+ code_mappings. extend ( covspans. into_iter ( ) . map ( |Covspan { span, bcb } | {
9296 // Each span produced by the refiner represents an ordinary code region.
9397 mappings:: CodeMapping { span, bcb }
9498 } ) ) ;
@@ -145,23 +149,6 @@ fn split_visible_macro_spans(covspans: &mut Vec<SpanFromMir>) {
145149 covspans. extend ( extra_spans) ;
146150}
147151
148- #[ derive( Debug ) ]
149- struct RefinedCovspan {
150- span : Span ,
151- bcb : BasicCoverageBlock ,
152- }
153-
154- impl RefinedCovspan {
155- fn is_mergeable ( & self , other : & Self ) -> bool {
156- self . bcb == other. bcb
157- }
158-
159- fn merge_from ( & mut self , other : & Self ) {
160- debug_assert ! ( self . is_mergeable( other) ) ;
161- self . span = self . span . to ( other. span ) ;
162- }
163- }
164-
165152/// Similar to `.drain(..)`, but stops just before it would remove an item not
166153/// satisfying the predicate.
167154fn drain_front_while < ' a , T > (
@@ -175,18 +162,18 @@ fn drain_front_while<'a, T>(
175162/// those spans by removing spans that overlap in unwanted ways, and by merging
176163/// compatible adjacent spans.
177164#[ instrument( level = "debug" ) ]
178- fn refine_sorted_spans ( sorted_spans : Vec < SpanFromMir > ) -> Vec < RefinedCovspan > {
165+ fn refine_sorted_spans ( sorted_spans : Vec < Covspan > ) -> Vec < Covspan > {
179166 // Holds spans that have been read from the input vector, but haven't yet
180167 // been committed to the output vector.
181168 let mut pending = vec ! [ ] ;
182169 let mut refined = vec ! [ ] ;
183170
184171 for curr in sorted_spans {
185- pending. retain ( |prev : & SpanFromMir | {
172+ pending. retain ( |prev : & Covspan | {
186173 if prev. span . hi ( ) <= curr. span . lo ( ) {
187174 // There's no overlap between the previous/current covspans,
188175 // so move the previous one into the refined list.
189- refined. push ( RefinedCovspan { span : prev. span , bcb : prev . bcb } ) ;
176+ refined. push ( prev. clone ( ) ) ;
190177 false
191178 } else {
192179 // Otherwise, retain the previous covspan only if it has the
@@ -199,26 +186,55 @@ fn refine_sorted_spans(sorted_spans: Vec<SpanFromMir>) -> Vec<RefinedCovspan> {
199186 }
200187
201188 // Drain the rest of the pending list into the refined list.
202- for prev in pending {
203- refined. push ( RefinedCovspan { span : prev. span , bcb : prev. bcb } ) ;
204- }
189+ refined. extend ( pending) ;
205190
206191 // Do one last merge pass, to simplify the output.
207192 debug ! ( ?refined, "before merge" ) ;
208- refined. dedup_by ( |b, a| {
209- if a. is_mergeable ( b) {
210- debug ! ( ?a, ?b, "merging list-adjacent refined spans" ) ;
211- a. merge_from ( b) ;
212- true
213- } else {
214- false
215- }
216- } ) ;
193+ refined. dedup_by ( |b, a| a. merge_if_eligible ( b) ) ;
217194 debug ! ( ?refined, "after merge" ) ;
218195
219196 refined
220197}
221198
199+ #[ derive( Clone , Debug ) ]
200+ struct Covspan {
201+ span : Span ,
202+ bcb : BasicCoverageBlock ,
203+ }
204+
205+ impl Covspan {
206+ /// Splits this covspan into 0-2 parts:
207+ /// - The part that is strictly before the hole span, if any.
208+ /// - The part that is strictly after the hole span, if any.
209+ fn split_around_hole_span ( & self , hole_span : Span ) -> ( Option < Self > , Option < Self > ) {
210+ let before = try {
211+ let span = self . span . trim_end ( hole_span) ?;
212+ Self { span, ..* self }
213+ } ;
214+ let after = try {
215+ let span = self . span . trim_start ( hole_span) ?;
216+ Self { span, ..* self }
217+ } ;
218+
219+ ( before, after)
220+ }
221+
222+ /// If `self` and `other` can be merged (i.e. they have the same BCB),
223+ /// mutates `self.span` to also include `other.span` and returns true.
224+ ///
225+ /// Note that compatible covspans can be merged even if their underlying
226+ /// spans are not overlapping/adjacent; any space between them will also be
227+ /// part of the merged covspan.
228+ fn merge_if_eligible ( & mut self , other : & Self ) -> bool {
229+ if self . bcb != other. bcb {
230+ return false ;
231+ }
232+
233+ self . span = self . span . to ( other. span ) ;
234+ true
235+ }
236+ }
237+
222238/// Compares two spans in (lo ascending, hi descending) order.
223239fn compare_spans ( a : Span , b : Span ) -> std:: cmp:: Ordering {
224240 // First sort by span start.
0 commit comments