@@ -20,37 +20,31 @@ pub(super) fn extract_refined_covspans(
20
20
basic_coverage_blocks : & CoverageGraph ,
21
21
code_mappings : & mut impl Extend < mappings:: CodeMapping > ,
22
22
) {
23
- let sorted_spans =
23
+ let sorted_span_buckets =
24
24
from_mir:: mir_to_initial_sorted_coverage_spans ( mir_body, hir_info, basic_coverage_blocks) ;
25
- let coverage_spans = SpansRefiner :: refine_sorted_spans ( sorted_spans) ;
26
- code_mappings. extend ( coverage_spans. into_iter ( ) . map ( |RefinedCovspan { bcb, span, .. } | {
27
- // Each span produced by the generator represents an ordinary code region.
28
- mappings:: CodeMapping { span, bcb }
29
- } ) ) ;
25
+ for bucket in sorted_span_buckets {
26
+ let refined_spans = SpansRefiner :: refine_sorted_spans ( bucket) ;
27
+ code_mappings. extend ( refined_spans. into_iter ( ) . map ( |RefinedCovspan { span, bcb } | {
28
+ // Each span produced by the refiner represents an ordinary code region.
29
+ mappings:: CodeMapping { span, bcb }
30
+ } ) ) ;
31
+ }
30
32
}
31
33
32
34
#[ derive( Debug ) ]
33
35
struct CurrCovspan {
34
36
span : Span ,
35
37
bcb : BasicCoverageBlock ,
36
- is_hole : bool ,
37
38
}
38
39
39
40
impl CurrCovspan {
40
- fn new ( span : Span , bcb : BasicCoverageBlock , is_hole : bool ) -> Self {
41
- Self { span, bcb, is_hole }
41
+ fn new ( span : Span , bcb : BasicCoverageBlock ) -> Self {
42
+ Self { span, bcb }
42
43
}
43
44
44
45
fn into_prev ( self ) -> PrevCovspan {
45
- let Self { span, bcb, is_hole } = self ;
46
- PrevCovspan { span, bcb, merged_spans : vec ! [ span] , is_hole }
47
- }
48
-
49
- fn into_refined ( self ) -> RefinedCovspan {
50
- // This is only called in cases where `curr` is a hole span that has
51
- // been carved out of `prev`.
52
- debug_assert ! ( self . is_hole) ;
53
- self . into_prev ( ) . into_refined ( )
46
+ let Self { span, bcb } = self ;
47
+ PrevCovspan { span, bcb, merged_spans : vec ! [ span] }
54
48
}
55
49
}
56
50
@@ -61,12 +55,11 @@ struct PrevCovspan {
61
55
/// List of all the original spans from MIR that have been merged into this
62
56
/// span. Mainly used to precisely skip over gaps when truncating a span.
63
57
merged_spans : Vec < Span > ,
64
- is_hole : bool ,
65
58
}
66
59
67
60
impl PrevCovspan {
68
61
fn is_mergeable ( & self , other : & CurrCovspan ) -> bool {
69
- self . bcb == other. bcb && ! self . is_hole && !other . is_hole
62
+ self . bcb == other. bcb
70
63
}
71
64
72
65
fn merge_from ( & mut self , other : & CurrCovspan ) {
@@ -84,27 +77,21 @@ impl PrevCovspan {
84
77
if self . merged_spans . is_empty ( ) { None } else { Some ( self . into_refined ( ) ) }
85
78
}
86
79
87
- fn refined_copy ( & self ) -> RefinedCovspan {
88
- let & Self { span, bcb, merged_spans : _, is_hole } = self ;
89
- RefinedCovspan { span, bcb, is_hole }
90
- }
91
-
92
80
fn into_refined ( self ) -> RefinedCovspan {
93
- // Even though we consume self, we can just reuse the copying impl.
94
- self . refined_copy ( )
81
+ let Self { span , bcb , merged_spans : _ } = self ;
82
+ RefinedCovspan { span , bcb }
95
83
}
96
84
}
97
85
98
86
#[ derive( Debug ) ]
99
87
struct RefinedCovspan {
100
88
span : Span ,
101
89
bcb : BasicCoverageBlock ,
102
- is_hole : bool ,
103
90
}
104
91
105
92
impl RefinedCovspan {
106
93
fn is_mergeable ( & self , other : & Self ) -> bool {
107
- self . bcb == other. bcb && ! self . is_hole && !other . is_hole
94
+ self . bcb == other. bcb
108
95
}
109
96
110
97
fn merge_from ( & mut self , other : & Self ) {
@@ -119,8 +106,6 @@ impl RefinedCovspan {
119
106
/// * Remove duplicate source code coverage regions
120
107
/// * Merge spans that represent continuous (both in source code and control flow), non-branching
121
108
/// execution
122
- /// * Carve out (leave uncovered) any "hole" spans that need to be left blank
123
- /// (e.g. closures that will be counted by their own MIR body)
124
109
struct SpansRefiner {
125
110
/// The initial set of coverage spans, sorted by `Span` (`lo` and `hi`) and by relative
126
111
/// dominance between the `BasicCoverageBlock`s of equal `Span`s.
@@ -181,13 +166,6 @@ impl SpansRefiner {
181
166
) ;
182
167
let prev = self . take_prev ( ) . into_refined ( ) ;
183
168
self . refined_spans . push ( prev) ;
184
- } else if prev. is_hole {
185
- // drop any equal or overlapping span (`curr`) and keep `prev` to test again in the
186
- // next iter
187
- debug ! ( ?prev, "prev (a hole) overlaps curr, so discarding curr" ) ;
188
- self . take_curr ( ) ; // Discards curr.
189
- } else if curr. is_hole {
190
- self . carve_out_span_for_hole ( ) ;
191
169
} else {
192
170
self . cutoff_prev_at_overlapping_curr ( ) ;
193
171
}
@@ -211,9 +189,6 @@ impl SpansRefiner {
211
189
}
212
190
} ) ;
213
191
214
- // Discard hole spans, since their purpose was to carve out chunks from
215
- // other spans, but we don't want the holes themselves in the final mappings.
216
- self . refined_spans . retain ( |covspan| !covspan. is_hole ) ;
217
192
self . refined_spans
218
193
}
219
194
@@ -249,50 +224,17 @@ impl SpansRefiner {
249
224
if let Some ( curr) = self . some_curr . take ( ) {
250
225
self . some_prev = Some ( curr. into_prev ( ) ) ;
251
226
}
252
- while let Some ( curr) = self . sorted_spans_iter . next ( ) {
253
- debug ! ( "FOR curr={:?}" , curr) ;
254
- if let Some ( prev) = & self . some_prev
255
- && prev. span . lo ( ) > curr. span . lo ( )
256
- {
257
- // Skip curr because prev has already advanced beyond the end of curr.
258
- // This can only happen if a prior iteration updated `prev` to skip past
259
- // a region of code, such as skipping past a hole.
260
- debug ! ( ?prev, "prev.span starts after curr.span, so curr will be dropped" ) ;
261
- } else {
262
- self . some_curr = Some ( CurrCovspan :: new ( curr. span , curr. bcb , curr. is_hole ) ) ;
263
- return true ;
227
+ if let Some ( SpanFromMir { span, bcb, .. } ) = self . sorted_spans_iter . next ( ) {
228
+ // This code only sees sorted spans after hole-carving, so there should
229
+ // be no way for `curr` to start before `prev`.
230
+ if let Some ( prev) = & self . some_prev {
231
+ debug_assert ! ( prev. span. lo( ) <= span. lo( ) ) ;
264
232
}
265
- }
266
- false
267
- }
268
-
269
- /// If `prev`s span extends left of the hole (`curr`), carve out the hole's span from
270
- /// `prev`'s span. Add the portion of the span to the left of the hole; and if the span
271
- /// extends to the right of the hole, update `prev` to that portion of the span.
272
- fn carve_out_span_for_hole ( & mut self ) {
273
- let prev = self . prev ( ) ;
274
- let curr = self . curr ( ) ;
275
-
276
- let left_cutoff = curr. span . lo ( ) ;
277
- let right_cutoff = curr. span . hi ( ) ;
278
- let has_pre_hole_span = prev. span . lo ( ) < right_cutoff;
279
- let has_post_hole_span = prev. span . hi ( ) > right_cutoff;
280
-
281
- if has_pre_hole_span {
282
- let mut pre_hole = prev. refined_copy ( ) ;
283
- pre_hole. span = pre_hole. span . with_hi ( left_cutoff) ;
284
- debug ! ( ?pre_hole, "prev overlaps a hole; adding pre-hole span" ) ;
285
- self . refined_spans . push ( pre_hole) ;
286
- }
287
-
288
- if has_post_hole_span {
289
- // Mutate `prev.span` to start after the hole (and discard curr).
290
- self . prev_mut ( ) . span = self . prev ( ) . span . with_lo ( right_cutoff) ;
291
- debug ! ( prev=?self . prev( ) , "mutated prev to start after the hole" ) ;
292
-
293
- // Prevent this curr from becoming prev.
294
- let hole_covspan = self . take_curr ( ) . into_refined ( ) ;
295
- self . refined_spans . push ( hole_covspan) ; // since self.prev() was already updated
233
+ self . some_curr = Some ( CurrCovspan :: new ( span, bcb) ) ;
234
+ debug ! ( ?self . some_prev, ?self . some_curr, "next_coverage_span" ) ;
235
+ true
236
+ } else {
237
+ false
296
238
}
297
239
}
298
240
0 commit comments