Skip to content

Commit 7aa1b83

Browse files
committed
coverage: Explain why we temporarily steal pending_dups
1 parent 5e5a8e7 commit 7aa1b83

File tree

1 file changed

+20
-6
lines changed
  • compiler/rustc_mir_transform/src/coverage

1 file changed

+20
-6
lines changed

compiler/rustc_mir_transform/src/coverage/spans.rs

+20-6
Original file line numberDiff line numberDiff line change
@@ -353,8 +353,10 @@ impl<'a> CoverageSpansGenerator<'a> {
353353

354354
let prev = self.take_prev();
355355
debug!(" AT END, adding last prev={prev:?}");
356-
let pending_dups = self.pending_dups.split_off(0);
357-
for dup in pending_dups {
356+
357+
// Take `pending_dups` so that we can drain it while calling self methods.
358+
// It is never used as a field after this point.
359+
for dup in std::mem::take(&mut self.pending_dups) {
358360
debug!(" ...adding at least one pending dup={:?}", dup);
359361
self.push_refined_span(dup);
360362
}
@@ -474,11 +476,16 @@ impl<'a> CoverageSpansGenerator<'a> {
474476
previous iteration, or prev started a new disjoint span"
475477
);
476478
if last_dup.span.hi() <= self.curr().span.lo() {
477-
let pending_dups = self.pending_dups.split_off(0);
478-
for dup in pending_dups.into_iter() {
479+
// Temporarily steal `pending_dups` into a local, so that we can
480+
// drain it while calling other self methods.
481+
let mut pending_dups = std::mem::take(&mut self.pending_dups);
482+
for dup in pending_dups.drain(..) {
479483
debug!(" ...adding at least one pending={:?}", dup);
480484
self.push_refined_span(dup);
481485
}
486+
// The list of dups is now empty, but we can recycle its capacity.
487+
assert!(pending_dups.is_empty() && self.pending_dups.is_empty());
488+
self.pending_dups = pending_dups;
482489
} else {
483490
self.pending_dups.clear();
484491
}
@@ -526,7 +533,10 @@ impl<'a> CoverageSpansGenerator<'a> {
526533
let has_pre_closure_span = prev.span.lo() < right_cutoff;
527534
let has_post_closure_span = prev.span.hi() > right_cutoff;
528535

529-
let mut pending_dups = self.pending_dups.split_off(0);
536+
// Temporarily steal `pending_dups` into a local, so that we can
537+
// mutate and/or drain it while calling other self methods.
538+
let mut pending_dups = std::mem::take(&mut self.pending_dups);
539+
530540
if has_pre_closure_span {
531541
let mut pre_closure = self.prev().clone();
532542
pre_closure.span = pre_closure.span.with_hi(left_cutoff);
@@ -540,6 +550,7 @@ impl<'a> CoverageSpansGenerator<'a> {
540550
}
541551
self.push_refined_span(pre_closure);
542552
}
553+
543554
if has_post_closure_span {
544555
// Mutate `prev.span()` to start after the closure (and discard curr).
545556
// (**NEVER** update `prev_original_span` because it affects the assumptions
@@ -550,12 +561,15 @@ impl<'a> CoverageSpansGenerator<'a> {
550561
debug!(" ...and at least one overlapping dup={:?}", dup);
551562
dup.span = dup.span.with_lo(right_cutoff);
552563
}
553-
self.pending_dups.append(&mut pending_dups);
554564
let closure_covspan = self.take_curr(); // Prevent this curr from becoming prev.
555565
self.push_refined_span(closure_covspan); // since self.prev() was already updated
556566
} else {
557567
pending_dups.clear();
558568
}
569+
570+
// Restore the modified post-closure spans, or the empty vector's capacity.
571+
assert!(self.pending_dups.is_empty());
572+
self.pending_dups = pending_dups;
559573
}
560574

561575
/// Called if `curr.span` equals `prev_original_span` (and potentially equal to all

0 commit comments

Comments
 (0)