11use std:: assert_matches:: assert_matches;
22use std:: collections:: hash_map:: Entry ;
3+ use std:: collections:: BTreeMap ;
34
45use rustc_data_structures:: fx:: FxHashMap ;
56use rustc_middle:: mir:: coverage:: { BlockMarkerId , BranchSpan , CoverageKind } ;
67use rustc_middle:: mir:: { self , BasicBlock , UnOp } ;
78use rustc_middle:: thir:: { ExprId , ExprKind , Thir } ;
89use rustc_middle:: ty:: TyCtxt ;
910use rustc_span:: def_id:: LocalDefId ;
11+ use rustc_span:: Span ;
1012
1113use crate :: build:: Builder ;
1214
@@ -16,6 +18,7 @@ pub(crate) struct BranchInfoBuilder {
1618
1719 num_block_markers : usize ,
1820 branch_spans : Vec < BranchSpan > ,
21+ pattern_match_branches : BTreeMap < Span , ( Vec < BasicBlock > , Vec < BasicBlock > ) > ,
1922}
2023
2124#[ derive( Clone , Copy ) ]
@@ -33,7 +36,12 @@ impl BranchInfoBuilder {
3336 /// is enabled and `def_id` represents a function that is eligible for coverage.
3437 pub ( crate ) fn new_if_enabled ( tcx : TyCtxt < ' _ > , def_id : LocalDefId ) -> Option < Self > {
3538 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+ } )
3745 } else {
3846 None
3947 }
@@ -86,7 +94,7 @@ impl BranchInfoBuilder {
8694 }
8795
8896 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 ;
9098
9199 if num_block_markers == 0 {
92100 assert ! ( branch_spans. is_empty( ) ) ;
@@ -143,4 +151,29 @@ impl Builder<'_, '_> {
143151 false_marker,
144152 } ) ;
145153 }
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+ }
146179}
0 commit comments