@@ -28,11 +28,15 @@ pub(super) fn extract_refined_covspans(
28
28
let ExtractedCovspans { mut covspans, mut holes } =
29
29
extract_covspans_and_holes_from_mir ( mir_body, hir_info, basic_coverage_blocks) ;
30
30
31
+ // First, perform the passes that need macro information.
31
32
covspans. sort_by ( |a, b| basic_coverage_blocks. cmp_in_dominator_order ( a. bcb , b. bcb ) ) ;
32
33
remove_unwanted_macro_spans ( & mut covspans) ;
33
34
split_visible_macro_spans ( & mut covspans) ;
34
35
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 | {
36
40
compare_spans ( a. span , b. span )
37
41
// After deduplication, we want to keep only the most-dominated BCB.
38
42
. then_with ( || basic_coverage_blocks. cmp_in_dominator_order ( a. bcb , b. bcb ) . reverse ( ) )
@@ -53,7 +57,7 @@ pub(super) fn extract_refined_covspans(
53
57
// and grouping them in buckets separated by the holes.
54
58
55
59
let mut input_covspans = VecDeque :: from ( covspans) ;
56
- let mut fragments: Vec < SpanFromMir > = vec ! [ ] ;
60
+ let mut fragments = vec ! [ ] ;
57
61
58
62
// For each hole:
59
63
// - Identify the spans that are entirely or partly before the hole.
@@ -88,7 +92,7 @@ pub(super) fn extract_refined_covspans(
88
92
covspans. sort_by ( compare_covspans) ;
89
93
90
94
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 } | {
92
96
// Each span produced by the refiner represents an ordinary code region.
93
97
mappings:: CodeMapping { span, bcb }
94
98
} ) ) ;
@@ -145,23 +149,6 @@ fn split_visible_macro_spans(covspans: &mut Vec<SpanFromMir>) {
145
149
covspans. extend ( extra_spans) ;
146
150
}
147
151
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
-
165
152
/// Similar to `.drain(..)`, but stops just before it would remove an item not
166
153
/// satisfying the predicate.
167
154
fn drain_front_while < ' a , T > (
@@ -175,18 +162,18 @@ fn drain_front_while<'a, T>(
175
162
/// those spans by removing spans that overlap in unwanted ways, and by merging
176
163
/// compatible adjacent spans.
177
164
#[ 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 > {
179
166
// Holds spans that have been read from the input vector, but haven't yet
180
167
// been committed to the output vector.
181
168
let mut pending = vec ! [ ] ;
182
169
let mut refined = vec ! [ ] ;
183
170
184
171
for curr in sorted_spans {
185
- pending. retain ( |prev : & SpanFromMir | {
172
+ pending. retain ( |prev : & Covspan | {
186
173
if prev. span . hi ( ) <= curr. span . lo ( ) {
187
174
// There's no overlap between the previous/current covspans,
188
175
// so move the previous one into the refined list.
189
- refined. push ( RefinedCovspan { span : prev. span , bcb : prev . bcb } ) ;
176
+ refined. push ( prev. clone ( ) ) ;
190
177
false
191
178
} else {
192
179
// Otherwise, retain the previous covspan only if it has the
@@ -199,26 +186,55 @@ fn refine_sorted_spans(sorted_spans: Vec<SpanFromMir>) -> Vec<RefinedCovspan> {
199
186
}
200
187
201
188
// 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) ;
205
190
206
191
// Do one last merge pass, to simplify the output.
207
192
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) ) ;
217
194
debug ! ( ?refined, "after merge" ) ;
218
195
219
196
refined
220
197
}
221
198
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
+
222
238
/// Compares two spans in (lo ascending, hi descending) order.
223
239
fn compare_spans ( a : Span , b : Span ) -> std:: cmp:: Ordering {
224
240
// First sort by span start.
0 commit comments