@@ -9,9 +9,10 @@ use rustc_middle::mir::{
9
9
} ;
10
10
use rustc_middle:: ty:: util:: Discr ;
11
11
use rustc_middle:: ty:: { self , TyCtxt } ;
12
+ use smallvec:: SmallVec ;
12
13
use tracing:: { debug, instrument} ;
13
14
14
- use crate :: drop_flag_effects:: DropFlagState ;
15
+ use crate :: drop_flag_effects:: { DropFlagState , InactiveVariants } ;
15
16
use crate :: move_paths:: { HasMoveData , InitIndex , InitKind , LookupResult , MoveData , MovePathIndex } ;
16
17
use crate :: {
17
18
Analysis , GenKill , MaybeReachable , drop_flag_effects, drop_flag_effects_for_function_entry,
@@ -26,6 +27,12 @@ pub struct MaybePlacesSwitchIntData<'tcx> {
26
27
}
27
28
28
29
impl < ' tcx > MaybePlacesSwitchIntData < ' tcx > {
30
+ /// Creates a `SmallVec` mapping each target in `targets` to its `VariantIdx`.
31
+ fn variants ( & mut self , targets : & mir:: SwitchTargets ) -> SmallVec < [ VariantIdx ; 4 ] > {
32
+ self . index = 0 ;
33
+ targets. all_values ( ) . iter ( ) . map ( |value| self . next_discr ( value. get ( ) ) ) . collect ( )
34
+ }
35
+
29
36
// The discriminant order in the `SwitchInt` targets should match the order yielded by
30
37
// `AdtDef::discriminants`. We rely on this to match each discriminant in the targets to its
31
38
// corresponding variant in linear time.
@@ -454,63 +461,24 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
454
461
data : & mut Self :: SwitchIntData ,
455
462
state : & mut Self :: Domain ,
456
463
value : SwitchTargetValue ,
457
- otherwise_state : Option < & mut Self :: Domain > ,
464
+ targets : & mir :: SwitchTargets ,
458
465
) {
459
- let SwitchTargetValue :: Normal ( value) = value else {
460
- return ;
466
+ let inactive_variants = match value {
467
+ SwitchTargetValue :: Normal ( value) => InactiveVariants :: Active ( data. next_discr ( value) ) ,
468
+ SwitchTargetValue :: Otherwise if self . exclude_inactive_in_otherwise => {
469
+ InactiveVariants :: Inactives ( data. variants ( targets) )
470
+ }
471
+ _ => return ,
461
472
} ;
462
473
463
- let handle_inactive_variant = |mpi| state. kill ( mpi) ;
464
-
465
474
// Kill all move paths that correspond to variants we know to be inactive along this
466
475
// particular outgoing edge of a `SwitchInt`.
467
- match otherwise_state {
468
- Some ( otherwise_state) => {
469
- drop_flag_effects:: on_all_variants (
470
- self . move_data ,
471
- data. enum_place ,
472
- data. next_discr ( value) ,
473
- handle_inactive_variant,
474
- |mpi| otherwise_state. kill ( mpi) ,
475
- ) ;
476
- }
477
- None => {
478
- drop_flag_effects:: on_all_variants (
479
- self . move_data ,
480
- data. enum_place ,
481
- data. next_discr ( value) ,
482
- handle_inactive_variant,
483
- |_mpi| { } ,
484
- ) ;
485
- }
486
- }
487
- }
488
-
489
- fn apply_switch_int_edge_effect_for_targets (
490
- & mut self ,
491
- targets : & mir:: SwitchTargets ,
492
- mut data : Self :: SwitchIntData ,
493
- state : & mut Self :: Domain ,
494
- mut propagate : impl FnMut ( mir:: BasicBlock , & Self :: Domain ) ,
495
- ) {
496
- let analyze_otherwise = self . exclude_inactive_in_otherwise
497
- && ( 1 ..data. discriminants . len ( ) ) . contains ( & targets. all_values ( ) . len ( ) ) ;
498
-
499
- let mut otherwise_state = if analyze_otherwise { Some ( state. clone ( ) ) } else { None } ;
500
- let mut target_state = MaybeReachable :: Unreachable ;
501
-
502
- for ( value, target) in targets. iter ( ) {
503
- target_state. clone_from ( & state) ;
504
- self . apply_switch_int_edge_effect (
505
- & mut data,
506
- & mut target_state,
507
- SwitchTargetValue :: Normal ( value) ,
508
- otherwise_state. as_mut ( ) ,
509
- ) ;
510
- propagate ( target, & target_state) ;
511
- }
512
-
513
- propagate ( targets. otherwise ( ) , otherwise_state. as_ref ( ) . unwrap_or ( state) ) ;
476
+ drop_flag_effects:: on_all_inactive_variants (
477
+ self . move_data ,
478
+ data. enum_place ,
479
+ & inactive_variants,
480
+ |mpi| state. kill ( mpi) ,
481
+ ) ;
514
482
}
515
483
}
516
484
@@ -613,63 +581,24 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
613
581
data : & mut Self :: SwitchIntData ,
614
582
state : & mut Self :: Domain ,
615
583
value : SwitchTargetValue ,
616
- otherwise_state : Option < & mut Self :: Domain > ,
584
+ targets : & mir :: SwitchTargets ,
617
585
) {
618
- let SwitchTargetValue :: Normal ( value) = value else {
619
- return ;
586
+ let inactive_variants = match value {
587
+ SwitchTargetValue :: Normal ( value) => InactiveVariants :: Active ( data. next_discr ( value) ) ,
588
+ SwitchTargetValue :: Otherwise if self . include_inactive_in_otherwise => {
589
+ InactiveVariants :: Inactives ( data. variants ( targets) )
590
+ }
591
+ _ => return ,
620
592
} ;
621
593
622
- let handle_inactive_variant = |mpi| state. gen_ ( mpi) ;
623
-
624
594
// Mark all move paths that correspond to variants other than this one as maybe
625
595
// uninitialized (in reality, they are *definitely* uninitialized).
626
- match otherwise_state {
627
- Some ( otherwise_state) => {
628
- drop_flag_effects:: on_all_variants (
629
- self . move_data ,
630
- data. enum_place ,
631
- data. next_discr ( value) ,
632
- handle_inactive_variant,
633
- |mpi| otherwise_state. gen_ ( mpi) ,
634
- ) ;
635
- }
636
- None => {
637
- drop_flag_effects:: on_all_variants (
638
- self . move_data ,
639
- data. enum_place ,
640
- data. next_discr ( value) ,
641
- handle_inactive_variant,
642
- |_mpi| { } ,
643
- ) ;
644
- }
645
- }
646
- }
647
-
648
- fn apply_switch_int_edge_effect_for_targets (
649
- & mut self ,
650
- targets : & mir:: SwitchTargets ,
651
- mut data : Self :: SwitchIntData ,
652
- state : & mut Self :: Domain ,
653
- mut propagate : impl FnMut ( mir:: BasicBlock , & Self :: Domain ) ,
654
- ) {
655
- let analyze_otherwise = self . include_inactive_in_otherwise
656
- && ( 1 ..data. discriminants . len ( ) ) . contains ( & targets. all_values ( ) . len ( ) ) ;
657
-
658
- let mut otherwise_state = if analyze_otherwise { Some ( state. clone ( ) ) } else { None } ;
659
- let mut target_state = MixedBitSet :: new_empty ( self . move_data ( ) . move_paths . len ( ) ) ;
660
-
661
- for ( value, target) in targets. iter ( ) {
662
- target_state. clone_from ( & state) ;
663
- self . apply_switch_int_edge_effect (
664
- & mut data,
665
- & mut target_state,
666
- SwitchTargetValue :: Normal ( value) ,
667
- otherwise_state. as_mut ( ) ,
668
- ) ;
669
- propagate ( target, & target_state) ;
670
- }
671
-
672
- propagate ( targets. otherwise ( ) , otherwise_state. as_ref ( ) . unwrap_or ( state) ) ;
596
+ drop_flag_effects:: on_all_inactive_variants (
597
+ self . move_data ,
598
+ data. enum_place ,
599
+ & inactive_variants,
600
+ |mpi| state. gen_ ( mpi) ,
601
+ ) ;
673
602
}
674
603
}
675
604
0 commit comments