1
+ mod matching;
1
2
use std:: cell:: Cell ;
2
3
use std:: collections:: VecDeque ;
3
4
use std:: rc:: Rc ;
4
5
6
+ use matching:: { LateMatchingState , MatchingDecisionCtx } ;
5
7
use rustc_data_structures:: fx:: FxIndexMap ;
6
8
use rustc_middle:: bug;
7
9
use rustc_middle:: mir:: BasicBlock ;
@@ -174,14 +176,17 @@ impl BooleanDecisionCtx {
174
176
#[ derive( Debug ) ]
175
177
enum DecisionCtx {
176
178
Boolean ( BooleanDecisionCtx ) ,
177
- #[ allow( unused) ]
178
- Matching ,
179
+ Matching ( MatchingDecisionCtx ) ,
179
180
}
180
181
181
182
impl DecisionCtx {
182
183
fn new_boolean ( id : DecisionId ) -> Self {
183
184
Self :: Boolean ( BooleanDecisionCtx :: new ( id) )
184
185
}
186
+
187
+ fn new_matching ( info : & [ ( Span , DecisionId ) ] ) -> Self {
188
+ Self :: Matching ( MatchingDecisionCtx :: new ( info) )
189
+ }
185
190
}
186
191
187
192
pub ( crate ) struct MCDCStateGuard {
@@ -270,6 +275,7 @@ pub(crate) struct MCDCInfoBuilder {
270
275
normal_branch_spans : Vec < MCDCBranchSpan > ,
271
276
mcdc_targets : FxIndexMap < DecisionId , MCDCTargetInfo > ,
272
277
state_stack : Vec < MCDCState > ,
278
+ late_matching_state : LateMatchingState ,
273
279
decision_id_gen : DecisionIdGen ,
274
280
}
275
281
@@ -279,6 +285,7 @@ impl MCDCInfoBuilder {
279
285
normal_branch_spans : vec ! [ ] ,
280
286
mcdc_targets : FxIndexMap :: default ( ) ,
281
287
state_stack : vec ! [ ] ,
288
+ late_matching_state : Default :: default ( ) ,
282
289
decision_id_gen : DecisionIdGen :: default ( ) ,
283
290
}
284
291
}
@@ -293,6 +300,11 @@ impl MCDCInfoBuilder {
293
300
& mut self . state_stack [ current_idx]
294
301
}
295
302
303
+ fn current_processing_ctx_mut ( & mut self ) -> Option < & mut DecisionCtx > {
304
+ self . ensure_active_state ( ) ;
305
+ self . state_stack . last_mut ( ) . and_then ( |state| state. current_ctx . as_mut ( ) )
306
+ }
307
+
296
308
fn ensure_active_state ( & mut self ) {
297
309
let mut active_state_idx = None ;
298
310
// Down to the first non-stashed state or non-empty state, which can be ensured to be
@@ -353,7 +365,8 @@ impl MCDCInfoBuilder {
353
365
let num_conditions = info. conditions . len ( ) ;
354
366
match num_conditions {
355
367
0 => {
356
- unreachable ! ( "Decision with no condition is not expected" ) ;
368
+ // Irrefutable patterns caused by empty types can lead to here.
369
+ false
357
370
}
358
371
// Ignore decisions with only one condition given that mcdc for them is completely equivalent to branch coverage.
359
372
2 ..=MAX_CONDITIONS_IN_DECISION => {
@@ -445,17 +458,26 @@ impl MCDCInfoBuilder {
445
458
446
459
let ( id, decision, conditions) = ctx. into_done ( ) ;
447
460
let info = MCDCTargetInfo { decision, conditions, nested_decisions_id } ;
448
- let entry_decision_id = self . append_mcdc_info ( tcx, id, info) . then_some ( id) ;
449
- self . on_ctx_finished ( tcx, entry_decision_id) ;
461
+ if self . late_matching_state . is_guard_decision ( id) {
462
+ self . late_matching_state . add_guard_decision ( id, info) ;
463
+ } else {
464
+ let entry_id = self . append_mcdc_info ( tcx, id, info) . then_some ( id) ;
465
+ self . on_ctx_finished ( tcx, entry_id)
466
+ }
450
467
}
451
468
452
469
pub ( crate ) fn into_done (
453
470
self ,
454
471
) -> ( Vec < MCDCBranchSpan > , Vec < ( MCDCDecisionSpan , Vec < MCDCBranchSpan > ) > ) {
472
+ assert ! (
473
+ !self . has_processing_decision( ) && self . late_matching_state. is_empty( ) ,
474
+ "has unfinished decisions"
475
+ ) ;
455
476
let MCDCInfoBuilder {
456
477
normal_branch_spans,
457
478
mcdc_targets,
458
479
state_stack : _,
480
+ late_matching_state : _,
459
481
decision_id_gen : _,
460
482
} = self ;
461
483
0 commit comments