@@ -26,45 +26,6 @@ pub(super) struct CoverageSpans {
26
26
}
27
27
28
28
impl CoverageSpans {
29
- /// Extracts coverage-relevant spans from MIR, and associates them with
30
- /// their corresponding BCBs.
31
- ///
32
- /// Returns `None` if no coverage-relevant spans could be extracted.
33
- pub ( super ) fn generate_coverage_spans (
34
- mir_body : & mir:: Body < ' _ > ,
35
- hir_info : & ExtractedHirInfo ,
36
- basic_coverage_blocks : & CoverageGraph ,
37
- ) -> Option < Self > {
38
- let mut mappings = vec ! [ ] ;
39
-
40
- let coverage_spans = CoverageSpansGenerator :: generate_coverage_spans (
41
- mir_body,
42
- hir_info,
43
- basic_coverage_blocks,
44
- ) ;
45
- mappings. extend ( coverage_spans. into_iter ( ) . map ( |CoverageSpan { bcb, span, .. } | {
46
- // Each span produced by the generator represents an ordinary code region.
47
- BcbMapping { kind : BcbMappingKind :: Code ( bcb) , span }
48
- } ) ) ;
49
-
50
- if mappings. is_empty ( ) {
51
- return None ;
52
- }
53
-
54
- // Identify which BCBs have one or more mappings.
55
- let mut bcb_has_mappings = BitSet :: new_empty ( basic_coverage_blocks. num_nodes ( ) ) ;
56
- let mut insert = |bcb| {
57
- bcb_has_mappings. insert ( bcb) ;
58
- } ;
59
- for & BcbMapping { kind, span : _ } in & mappings {
60
- match kind {
61
- BcbMappingKind :: Code ( bcb) => insert ( bcb) ,
62
- }
63
- }
64
-
65
- Some ( Self { bcb_has_mappings, mappings } )
66
- }
67
-
68
29
pub ( super ) fn bcb_has_coverage_spans ( & self , bcb : BasicCoverageBlock ) -> bool {
69
30
self . bcb_has_mappings . contains ( bcb)
70
31
}
@@ -74,6 +35,43 @@ impl CoverageSpans {
74
35
}
75
36
}
76
37
38
+ /// Extracts coverage-relevant spans from MIR, and associates them with
39
+ /// their corresponding BCBs.
40
+ ///
41
+ /// Returns `None` if no coverage-relevant spans could be extracted.
42
+ pub ( super ) fn generate_coverage_spans (
43
+ mir_body : & mir:: Body < ' _ > ,
44
+ hir_info : & ExtractedHirInfo ,
45
+ basic_coverage_blocks : & CoverageGraph ,
46
+ ) -> Option < CoverageSpans > {
47
+ let mut mappings = vec ! [ ] ;
48
+
49
+ let sorted_spans =
50
+ from_mir:: mir_to_initial_sorted_coverage_spans ( mir_body, hir_info, basic_coverage_blocks) ;
51
+ let coverage_spans = SpansRefiner :: refine_sorted_spans ( basic_coverage_blocks, sorted_spans) ;
52
+ mappings. extend ( coverage_spans. into_iter ( ) . map ( |CoverageSpan { bcb, span, .. } | {
53
+ // Each span produced by the generator represents an ordinary code region.
54
+ BcbMapping { kind : BcbMappingKind :: Code ( bcb) , span }
55
+ } ) ) ;
56
+
57
+ if mappings. is_empty ( ) {
58
+ return None ;
59
+ }
60
+
61
+ // Identify which BCBs have one or more mappings.
62
+ let mut bcb_has_mappings = BitSet :: new_empty ( basic_coverage_blocks. num_nodes ( ) ) ;
63
+ let mut insert = |bcb| {
64
+ bcb_has_mappings. insert ( bcb) ;
65
+ } ;
66
+ for & BcbMapping { kind, span : _ } in & mappings {
67
+ match kind {
68
+ BcbMappingKind :: Code ( bcb) => insert ( bcb) ,
69
+ }
70
+ }
71
+
72
+ Some ( CoverageSpans { bcb_has_mappings, mappings } )
73
+ }
74
+
77
75
/// A BCB is deconstructed into one or more `Span`s. Each `Span` maps to a `CoverageSpan` that
78
76
/// references the originating BCB and one or more MIR `Statement`s and/or `Terminator`s.
79
77
/// Initially, the `Span`s come from the `Statement`s and `Terminator`s, but subsequent
@@ -130,7 +128,7 @@ impl CoverageSpan {
130
128
/// * Merge spans that represent continuous (both in source code and control flow), non-branching
131
129
/// execution
132
130
/// * Carve out (leave uncovered) any span that will be counted by another MIR (notably, closures)
133
- struct CoverageSpansGenerator < ' a > {
131
+ struct SpansRefiner < ' a > {
134
132
/// The BasicCoverageBlock Control Flow Graph (BCB CFG).
135
133
basic_coverage_blocks : & ' a CoverageGraph ,
136
134
@@ -173,40 +171,15 @@ struct CoverageSpansGenerator<'a> {
173
171
refined_spans : Vec < CoverageSpan > ,
174
172
}
175
173
176
- impl < ' a > CoverageSpansGenerator < ' a > {
177
- /// Generate a minimal set of `CoverageSpan`s, each representing a contiguous code region to be
178
- /// counted.
179
- ///
180
- /// The basic steps are:
181
- ///
182
- /// 1. Extract an initial set of spans from the `Statement`s and `Terminator`s of each
183
- /// `BasicCoverageBlockData`.
184
- /// 2. Sort the spans by span.lo() (starting position). Spans that start at the same position
185
- /// are sorted with longer spans before shorter spans; and equal spans are sorted
186
- /// (deterministically) based on "dominator" relationship (if any).
187
- /// 3. Traverse the spans in sorted order to identify spans that can be dropped (for instance,
188
- /// if another span or spans are already counting the same code region), or should be merged
189
- /// into a broader combined span (because it represents a contiguous, non-branching, and
190
- /// uninterrupted region of source code).
191
- ///
192
- /// Closures are exposed in their enclosing functions as `Assign` `Rvalue`s, and since
193
- /// closures have their own MIR, their `Span` in their enclosing function should be left
194
- /// "uncovered".
195
- ///
196
- /// Note the resulting vector of `CoverageSpan`s may not be fully sorted (and does not need
197
- /// to be).
198
- pub ( super ) fn generate_coverage_spans (
199
- mir_body : & mir:: Body < ' _ > ,
200
- hir_info : & ExtractedHirInfo ,
174
+ impl < ' a > SpansRefiner < ' a > {
175
+ /// Takes the initial list of (sorted) spans extracted from MIR, and "refines"
176
+ /// them by merging compatible adjacent spans, removing redundant spans,
177
+ /// and carving holes in spans when they overlap in unwanted ways.
178
+ fn refine_sorted_spans (
201
179
basic_coverage_blocks : & ' a CoverageGraph ,
180
+ sorted_spans : Vec < CoverageSpan > ,
202
181
) -> Vec < CoverageSpan > {
203
- let sorted_spans = from_mir:: mir_to_initial_sorted_coverage_spans (
204
- mir_body,
205
- hir_info,
206
- basic_coverage_blocks,
207
- ) ;
208
-
209
- let coverage_spans = Self {
182
+ let this = Self {
210
183
basic_coverage_blocks,
211
184
sorted_spans_iter : sorted_spans. into_iter ( ) ,
212
185
some_curr : None ,
@@ -217,7 +190,7 @@ impl<'a> CoverageSpansGenerator<'a> {
217
190
refined_spans : Vec :: with_capacity ( basic_coverage_blocks. num_nodes ( ) * 2 ) ,
218
191
} ;
219
192
220
- coverage_spans . to_refined_spans ( )
193
+ this . to_refined_spans ( )
221
194
}
222
195
223
196
/// Iterate through the sorted `CoverageSpan`s, and return the refined list of merged and
0 commit comments