@@ -7,9 +7,7 @@ use rustc_middle::bug;
7
7
use rustc_middle:: mir:: {
8
8
self , Body , CallReturnPlaces , Location , SwitchTargetValue , TerminatorEdges ,
9
9
} ;
10
- use rustc_middle:: ty:: util:: Discr ;
11
- use rustc_middle:: ty:: { self , TyCtxt } ;
12
- use smallvec:: SmallVec ;
10
+ use rustc_middle:: ty:: { self , AdtDef , TyCtxt } ;
13
11
use tracing:: { debug, instrument} ;
14
12
15
13
use crate :: drop_flag_effects:: { DropFlagState , InactiveVariants } ;
@@ -22,30 +20,25 @@ use crate::{
22
20
// Used by both `MaybeInitializedPlaces` and `MaybeUninitializedPlaces`.
23
21
pub struct MaybePlacesSwitchIntData < ' tcx > {
24
22
enum_place : mir:: Place < ' tcx > ,
25
- discriminants : Vec < ( VariantIdx , Discr < ' tcx > ) > ,
26
- index : usize ,
23
+ targets : Vec < ( VariantIdx , mir:: BasicBlock ) > ,
27
24
}
28
25
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
-
36
- // The discriminant order in the `SwitchInt` targets should match the order yielded by
37
- // `AdtDef::discriminants`. We rely on this to match each discriminant in the targets to its
38
- // corresponding variant in linear time.
39
- fn next_discr ( & mut self , value : u128 ) -> VariantIdx {
40
- // An out-of-bounds abort will occur if the discriminant ordering isn't as described above.
41
- loop {
42
- let ( variant, discr) = self . discriminants [ self . index ] ;
43
- self . index += 1 ;
44
- if discr. val == value {
45
- return variant;
46
- }
47
- }
48
- }
26
+ /// Maps values of targets in `SwitchTargets` to `(VariantIdx, BasicBlock).` Panics if the variants
27
+ /// in `targets` aren't in the same order as `AdtDef::discriminants`.
28
+ fn collect_switch_targets < ' tcx > (
29
+ enum_def : AdtDef < ' tcx > ,
30
+ targets : & mir:: SwitchTargets ,
31
+ tcx : TyCtxt < ' tcx > ,
32
+ ) -> Vec < ( VariantIdx , mir:: BasicBlock ) > {
33
+ let mut discriminants = enum_def. discriminants ( tcx) ;
34
+
35
+ Vec :: from_iter ( targets. iter ( ) . map ( |( value, bb) | {
36
+ let Some ( ( variant_idx, _) ) = discriminants. find ( |( _, discr) | discr. val == value) else {
37
+ bug ! ( "ran out of discriminants before matching all switch targets" ) ;
38
+ } ;
39
+
40
+ ( variant_idx, bb)
41
+ } ) )
49
42
}
50
43
51
44
impl < ' tcx > MaybePlacesSwitchIntData < ' tcx > {
@@ -54,6 +47,7 @@ impl<'tcx> MaybePlacesSwitchIntData<'tcx> {
54
47
body : & Body < ' tcx > ,
55
48
block : mir:: BasicBlock ,
56
49
discr : & mir:: Operand < ' tcx > ,
50
+ targets : & mir:: SwitchTargets ,
57
51
) -> Option < Self > {
58
52
let Some ( discr) = discr. place ( ) else { return None } ;
59
53
@@ -78,8 +72,7 @@ impl<'tcx> MaybePlacesSwitchIntData<'tcx> {
78
72
ty:: Adt ( enum_def, _) => {
79
73
return Some ( MaybePlacesSwitchIntData {
80
74
enum_place,
81
- discriminants : enum_def. discriminants ( tcx) . collect ( ) ,
82
- index : 0 ,
75
+ targets : collect_switch_targets ( * enum_def, targets, tcx) ,
83
76
} ) ;
84
77
}
85
78
@@ -448,25 +441,32 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
448
441
& mut self ,
449
442
block : mir:: BasicBlock ,
450
443
discr : & mir:: Operand < ' tcx > ,
444
+ targets : & mir:: SwitchTargets ,
451
445
) -> Option < Self :: SwitchIntData > {
452
446
if !self . tcx . sess . opts . unstable_opts . precise_enum_drop_elaboration {
453
447
return None ;
454
448
}
455
449
456
- MaybePlacesSwitchIntData :: new ( self . tcx , self . body , block, discr)
450
+ MaybePlacesSwitchIntData :: new ( self . tcx , self . body , block, discr, targets)
451
+ }
452
+
453
+ #[ inline]
454
+ fn switch_int_target_variants < ' a > (
455
+ data : & ' a Self :: SwitchIntData ,
456
+ ) -> impl Iterator < Item = & ' a ( VariantIdx , mir:: BasicBlock ) > {
457
+ data. targets . iter ( )
457
458
}
458
459
459
460
fn apply_switch_int_edge_effect (
460
461
& mut self ,
461
- data : & mut Self :: SwitchIntData ,
462
+ data : & Self :: SwitchIntData ,
462
463
state : & mut Self :: Domain ,
463
464
value : SwitchTargetValue ,
464
- targets : & mir:: SwitchTargets ,
465
465
) {
466
466
let inactive_variants = match value {
467
- SwitchTargetValue :: Normal ( value ) => InactiveVariants :: Active ( data . next_discr ( value ) ) ,
467
+ SwitchTargetValue :: Normal ( variant_idx ) => InactiveVariants :: Active ( variant_idx ) ,
468
468
SwitchTargetValue :: Otherwise if self . exclude_inactive_in_otherwise => {
469
- InactiveVariants :: Inactives ( data. variants ( targets) )
469
+ InactiveVariants :: Inactives ( & data. targets )
470
470
}
471
471
_ => return ,
472
472
} ;
@@ -564,6 +564,7 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
564
564
& mut self ,
565
565
block : mir:: BasicBlock ,
566
566
discr : & mir:: Operand < ' tcx > ,
567
+ targets : & mir:: SwitchTargets ,
567
568
) -> Option < Self :: SwitchIntData > {
568
569
if !self . tcx . sess . opts . unstable_opts . precise_enum_drop_elaboration {
569
570
return None ;
@@ -573,20 +574,26 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
573
574
return None ;
574
575
}
575
576
576
- MaybePlacesSwitchIntData :: new ( self . tcx , self . body , block, discr)
577
+ MaybePlacesSwitchIntData :: new ( self . tcx , self . body , block, discr, targets)
578
+ }
579
+
580
+ #[ inline]
581
+ fn switch_int_target_variants < ' a > (
582
+ data : & ' a Self :: SwitchIntData ,
583
+ ) -> impl Iterator < Item = & ' a ( VariantIdx , mir:: BasicBlock ) > {
584
+ data. targets . iter ( )
577
585
}
578
586
579
587
fn apply_switch_int_edge_effect (
580
588
& mut self ,
581
- data : & mut Self :: SwitchIntData ,
589
+ data : & Self :: SwitchIntData ,
582
590
state : & mut Self :: Domain ,
583
591
value : SwitchTargetValue ,
584
- targets : & mir:: SwitchTargets ,
585
592
) {
586
593
let inactive_variants = match value {
587
- SwitchTargetValue :: Normal ( value ) => InactiveVariants :: Active ( data . next_discr ( value ) ) ,
594
+ SwitchTargetValue :: Normal ( variant_idx ) => InactiveVariants :: Active ( variant_idx ) ,
588
595
SwitchTargetValue :: Otherwise if self . include_inactive_in_otherwise => {
589
- InactiveVariants :: Inactives ( data. variants ( targets) )
596
+ InactiveVariants :: Inactives ( & data. targets )
590
597
}
591
598
_ => return ,
592
599
} ;
0 commit comments