@@ -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