1
1
use std:: assert_matches:: assert_matches;
2
2
use std:: collections:: hash_map:: Entry ;
3
+ use std:: collections:: BTreeMap ;
3
4
4
5
use rustc_data_structures:: fx:: FxHashMap ;
5
6
use rustc_middle:: mir:: coverage:: { BlockMarkerId , BranchSpan , CoverageKind } ;
6
7
use rustc_middle:: mir:: { self , BasicBlock , UnOp } ;
7
8
use rustc_middle:: thir:: { ExprId , ExprKind , Thir } ;
8
9
use rustc_middle:: ty:: TyCtxt ;
9
10
use rustc_span:: def_id:: LocalDefId ;
11
+ use rustc_span:: Span ;
10
12
11
13
use crate :: build:: Builder ;
12
14
@@ -16,6 +18,7 @@ pub(crate) struct BranchInfoBuilder {
16
18
17
19
num_block_markers : usize ,
18
20
branch_spans : Vec < BranchSpan > ,
21
+ pattern_match_branches : BTreeMap < Span , ( Vec < BasicBlock > , Vec < BasicBlock > ) > ,
19
22
}
20
23
21
24
#[ derive( Clone , Copy ) ]
@@ -33,7 +36,12 @@ impl BranchInfoBuilder {
33
36
/// is enabled and `def_id` represents a function that is eligible for coverage.
34
37
pub ( crate ) fn new_if_enabled ( tcx : TyCtxt < ' _ > , def_id : LocalDefId ) -> Option < Self > {
35
38
if tcx. sess . instrument_coverage_branch ( ) && tcx. is_eligible_for_coverage ( def_id) {
36
- Some ( Self { nots : FxHashMap :: default ( ) , num_block_markers : 0 , branch_spans : vec ! [ ] } )
39
+ Some ( Self {
40
+ nots : FxHashMap :: default ( ) ,
41
+ num_block_markers : 0 ,
42
+ branch_spans : vec ! [ ] ,
43
+ pattern_match_branches : BTreeMap :: new ( ) ,
44
+ } )
37
45
} else {
38
46
None
39
47
}
@@ -86,7 +94,7 @@ impl BranchInfoBuilder {
86
94
}
87
95
88
96
pub ( crate ) fn into_done ( self ) -> Option < Box < mir:: coverage:: BranchInfo > > {
89
- let Self { nots : _, num_block_markers, branch_spans } = self ;
97
+ let Self { nots : _, num_block_markers, branch_spans, .. } = self ;
90
98
91
99
if num_block_markers == 0 {
92
100
assert ! ( branch_spans. is_empty( ) ) ;
@@ -143,4 +151,29 @@ impl Builder<'_, '_> {
143
151
false_marker,
144
152
} ) ;
145
153
}
154
+
155
+ #[ allow( unused) ]
156
+ pub ( crate ) fn visit_pattern_match_branches (
157
+ & mut self ,
158
+ targets : impl Iterator < Item = ( Span , BasicBlock ) > ,
159
+ otherwise_block : BasicBlock ,
160
+ ) {
161
+ // TODO! Add get_block_marker_id here to transform BasicBlock to BlockMarkerId then `pattern_match_branches` could store BlockMarkerId.
162
+ let targets = targets. collect :: < Vec < _ > > ( ) ;
163
+
164
+ let Some ( branch_info) = self . coverage_branch_info . as_mut ( ) else { return } ;
165
+ for ( span, true_blk) in & targets {
166
+ let ( true_blks, false_blks) =
167
+ branch_info. pattern_match_branches . entry ( * span) . or_insert_with ( || ( vec ! [ ] , vec ! [ ] ) ) ;
168
+ // SomeEnum::A | SomeEnum::B would be lowered to something like switchInt(_1) -> [ 0: bb1, 1: bb3, otherwise: otherwise_block ]
169
+ // Thus bb3 and otherwise_block both are false blocks for SomeEnum::A.
170
+ true_blks. push ( * true_blk) ;
171
+ false_blks. extend (
172
+ targets
173
+ . iter ( )
174
+ . filter_map ( |( _, blk) | ( blk != true_blk) . then_some ( * blk) )
175
+ . chain ( std:: iter:: once ( otherwise_block) ) ,
176
+ ) ;
177
+ }
178
+ }
146
179
}
0 commit comments