@@ -89,10 +89,10 @@ impl CoverageSpan {
8989 }
9090 }
9191
92- pub fn merge_from ( & mut self , mut other : CoverageSpan ) {
93- debug_assert ! ( self . is_mergeable( & other) ) ;
92+ pub fn merge_from ( & mut self , other : & Self ) {
93+ debug_assert ! ( self . is_mergeable( other) ) ;
9494 self . span = self . span . to ( other. span ) ;
95- self . merged_spans . append ( & mut other. merged_spans ) ;
95+ self . merged_spans . extend_from_slice ( & other. merged_spans ) ;
9696 }
9797
9898 pub fn cutoff_statements_at ( & mut self , cutoff_pos : BytePos ) {
@@ -267,15 +267,15 @@ impl<'a> CoverageSpansGenerator<'a> {
267267 if curr. is_mergeable ( prev) {
268268 debug ! ( " same bcb (and neither is a closure), merge with prev={prev:?}" ) ;
269269 let prev = self . take_prev ( ) ;
270- self . curr_mut ( ) . merge_from ( prev) ;
270+ self . curr_mut ( ) . merge_from ( & prev) ;
271271 self . maybe_push_macro_name_span ( ) ;
272272 // Note that curr.span may now differ from curr_original_span
273273 } else if prev. span . hi ( ) <= curr. span . lo ( ) {
274274 debug ! (
275275 " different bcbs and disjoint spans, so keep curr for next iter, and add prev={prev:?}" ,
276276 ) ;
277277 let prev = self . take_prev ( ) ;
278- self . push_refined_span ( prev) ;
278+ self . refined_spans . push ( prev) ;
279279 self . maybe_push_macro_name_span ( ) ;
280280 } else if prev. is_closure {
281281 // drop any equal or overlapping span (`curr`) and keep `prev` to test again in the
@@ -322,11 +322,10 @@ impl<'a> CoverageSpansGenerator<'a> {
322322 let prev = self . take_prev ( ) ;
323323 debug ! ( " AT END, adding last prev={prev:?}" ) ;
324324
325- // Take `pending_dups` so that we can drain it while calling self methods.
326- // It is never used as a field after this point.
327- for dup in std:: mem:: take ( & mut self . pending_dups ) {
325+ // Drain any remaining dups into the output.
326+ for dup in self . pending_dups . drain ( ..) {
328327 debug ! ( " ...adding at least one pending dup={:?}" , dup) ;
329- self . push_refined_span ( dup) ;
328+ self . refined_spans . push ( dup) ;
330329 }
331330
332331 // Async functions wrap a closure that implements the body to be executed. The enclosing
@@ -343,28 +342,27 @@ impl<'a> CoverageSpansGenerator<'a> {
343342 } ;
344343
345344 if !body_ends_with_closure {
346- self . push_refined_span ( prev) ;
345+ self . refined_spans . push ( prev) ;
347346 }
348347
348+ // Do one last merge pass, to simplify the output.
349+ self . refined_spans . dedup_by ( |b, a| {
350+ if a. is_mergeable ( b) {
351+ debug ! ( ?a, ?b, "merging list-adjacent refined spans" ) ;
352+ a. merge_from ( b) ;
353+ true
354+ } else {
355+ false
356+ }
357+ } ) ;
358+
349359 // Remove `CoverageSpan`s derived from closures, originally added to ensure the coverage
350360 // regions for the current function leave room for the closure's own coverage regions
351361 // (injected separately, from the closure's own MIR).
352362 self . refined_spans . retain ( |covspan| !covspan. is_closure ) ;
353363 self . refined_spans
354364 }
355365
356- fn push_refined_span ( & mut self , covspan : CoverageSpan ) {
357- if let Some ( last) = self . refined_spans . last_mut ( )
358- && last. is_mergeable ( & covspan)
359- {
360- // Instead of pushing the new span, merge it with the last refined span.
361- debug ! ( ?last, ?covspan, "merging new refined span with last refined span" ) ;
362- last. merge_from ( covspan) ;
363- } else {
364- self . refined_spans . push ( covspan) ;
365- }
366- }
367-
368366 /// If `curr` is part of a new macro expansion, carve out and push a separate
369367 /// span that ends just after the macro name and its subsequent `!`.
370368 fn maybe_push_macro_name_span ( & mut self ) {
@@ -397,7 +395,7 @@ impl<'a> CoverageSpansGenerator<'a> {
397395 " and curr starts a new macro expansion, so add a new span just for \
398396 the macro `{visible_macro}!`, new span={macro_name_cov:?}",
399397 ) ;
400- self . push_refined_span ( macro_name_cov) ;
398+ self . refined_spans . push ( macro_name_cov) ;
401399 }
402400
403401 fn curr ( & self ) -> & CoverageSpan {
@@ -454,19 +452,14 @@ impl<'a> CoverageSpansGenerator<'a> {
454452 previous iteration, or prev started a new disjoint span"
455453 ) ;
456454 if last_dup. span . hi ( ) <= self . curr ( ) . span . lo ( ) {
457- // Temporarily steal `pending_dups` into a local, so that we can
458- // drain it while calling other self methods.
459- let mut pending_dups = std:: mem:: take ( & mut self . pending_dups ) ;
460- for dup in pending_dups. drain ( ..) {
455+ for dup in self . pending_dups . drain ( ..) {
461456 debug ! ( " ...adding at least one pending={:?}" , dup) ;
462- self . push_refined_span ( dup) ;
457+ self . refined_spans . push ( dup) ;
463458 }
464- // The list of dups is now empty, but we can recycle its capacity.
465- assert ! ( pending_dups. is_empty( ) && self . pending_dups. is_empty( ) ) ;
466- self . pending_dups = pending_dups;
467459 } else {
468460 self . pending_dups . clear ( ) ;
469461 }
462+ assert ! ( self . pending_dups. is_empty( ) ) ;
470463 }
471464
472465 /// Advance `prev` to `curr` (if any), and `curr` to the next `CoverageSpan` in sorted order.
@@ -513,22 +506,18 @@ impl<'a> CoverageSpansGenerator<'a> {
513506 let has_pre_closure_span = prev. span . lo ( ) < right_cutoff;
514507 let has_post_closure_span = prev. span . hi ( ) > right_cutoff;
515508
516- // Temporarily steal `pending_dups` into a local, so that we can
517- // mutate and/or drain it while calling other self methods.
518- let mut pending_dups = std:: mem:: take ( & mut self . pending_dups ) ;
519-
520509 if has_pre_closure_span {
521510 let mut pre_closure = self . prev ( ) . clone ( ) ;
522511 pre_closure. span = pre_closure. span . with_hi ( left_cutoff) ;
523512 debug ! ( " prev overlaps a closure. Adding span for pre_closure={:?}" , pre_closure) ;
524- if !pending_dups. is_empty ( ) {
525- for mut dup in pending_dups. iter ( ) . cloned ( ) {
526- dup. span = dup. span . with_hi ( left_cutoff) ;
527- debug ! ( " ...and at least one pre_closure dup={:?}" , dup) ;
528- self . push_refined_span ( dup) ;
529- }
513+
514+ for mut dup in self . pending_dups . iter ( ) . cloned ( ) {
515+ dup. span = dup. span . with_hi ( left_cutoff) ;
516+ debug ! ( " ...and at least one pre_closure dup={:?}" , dup) ;
517+ self . refined_spans . push ( dup) ;
530518 }
531- self . push_refined_span ( pre_closure) ;
519+
520+ self . refined_spans . push ( pre_closure) ;
532521 }
533522
534523 if has_post_closure_span {
@@ -537,19 +526,17 @@ impl<'a> CoverageSpansGenerator<'a> {
537526 // about how the `CoverageSpan`s are ordered.)
538527 self . prev_mut ( ) . span = self . prev ( ) . span . with_lo ( right_cutoff) ;
539528 debug ! ( " Mutated prev.span to start after the closure. prev={:?}" , self . prev( ) ) ;
540- for dup in pending_dups. iter_mut ( ) {
529+
530+ for dup in & mut self . pending_dups {
541531 debug ! ( " ...and at least one overlapping dup={:?}" , dup) ;
542532 dup. span = dup. span . with_lo ( right_cutoff) ;
543533 }
534+
544535 let closure_covspan = self . take_curr ( ) ; // Prevent this curr from becoming prev.
545- self . push_refined_span ( closure_covspan) ; // since self.prev() was already updated
536+ self . refined_spans . push ( closure_covspan) ; // since self.prev() was already updated
546537 } else {
547- pending_dups. clear ( ) ;
538+ self . pending_dups . clear ( ) ;
548539 }
549-
550- // Restore the modified post-closure spans, or the empty vector's capacity.
551- assert ! ( self . pending_dups. is_empty( ) ) ;
552- self . pending_dups = pending_dups;
553540 }
554541
555542 /// Called if `curr.span` equals `prev_original_span` (and potentially equal to all
@@ -645,7 +632,7 @@ impl<'a> CoverageSpansGenerator<'a> {
645632 } else {
646633 debug ! ( " ... adding modified prev={:?}" , self . prev( ) ) ;
647634 let prev = self . take_prev ( ) ;
648- self . push_refined_span ( prev) ;
635+ self . refined_spans . push ( prev) ;
649636 }
650637 } else {
651638 // with `pending_dups`, `prev` cannot have any statements that don't overlap
0 commit comments