@@ -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
@@ -451,25 +444,32 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
451
444
& mut self ,
452
445
block : mir:: BasicBlock ,
453
446
discr : & mir:: Operand < ' tcx > ,
447
+ targets : & mir:: SwitchTargets ,
454
448
) -> Option < Self :: SwitchIntData > {
455
449
if !self . tcx . sess . opts . unstable_opts . precise_enum_drop_elaboration {
456
450
return None ;
457
451
}
458
452
459
- MaybePlacesSwitchIntData :: new ( self . tcx , self . body , block, discr)
453
+ MaybePlacesSwitchIntData :: new ( self . tcx , self . body , block, discr, targets)
454
+ }
455
+
456
+ #[ inline]
457
+ fn switch_int_target_variants < ' a > (
458
+ data : & ' a Self :: SwitchIntData ,
459
+ ) -> impl Iterator < Item = & ' a ( VariantIdx , mir:: BasicBlock ) > {
460
+ data. targets . iter ( )
460
461
}
461
462
462
463
fn apply_switch_int_edge_effect (
463
464
& mut self ,
464
- data : & mut Self :: SwitchIntData ,
465
+ data : & Self :: SwitchIntData ,
465
466
state : & mut Self :: Domain ,
466
467
value : SwitchTargetValue ,
467
- targets : & mir:: SwitchTargets ,
468
468
) {
469
469
let inactive_variants = match value {
470
- SwitchTargetValue :: Normal ( value ) => InactiveVariants :: Active ( data . next_discr ( value ) ) ,
470
+ SwitchTargetValue :: Normal ( variant_idx ) => InactiveVariants :: Active ( variant_idx ) ,
471
471
SwitchTargetValue :: Otherwise if self . exclude_inactive_in_otherwise => {
472
- InactiveVariants :: Inactives ( data. variants ( targets) )
472
+ InactiveVariants :: Inactives ( & data. targets )
473
473
}
474
474
_ => return ,
475
475
} ;
@@ -567,6 +567,7 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
567
567
& mut self ,
568
568
block : mir:: BasicBlock ,
569
569
discr : & mir:: Operand < ' tcx > ,
570
+ targets : & mir:: SwitchTargets ,
570
571
) -> Option < Self :: SwitchIntData > {
571
572
if !self . tcx . sess . opts . unstable_opts . precise_enum_drop_elaboration {
572
573
return None ;
@@ -576,20 +577,26 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
576
577
return None ;
577
578
}
578
579
579
- MaybePlacesSwitchIntData :: new ( self . tcx , self . body , block, discr)
580
+ MaybePlacesSwitchIntData :: new ( self . tcx , self . body , block, discr, targets)
581
+ }
582
+
583
+ #[ inline]
584
+ fn switch_int_target_variants < ' a > (
585
+ data : & ' a Self :: SwitchIntData ,
586
+ ) -> impl Iterator < Item = & ' a ( VariantIdx , mir:: BasicBlock ) > {
587
+ data. targets . iter ( )
580
588
}
581
589
582
590
fn apply_switch_int_edge_effect (
583
591
& mut self ,
584
- data : & mut Self :: SwitchIntData ,
592
+ data : & Self :: SwitchIntData ,
585
593
state : & mut Self :: Domain ,
586
594
value : SwitchTargetValue ,
587
- targets : & mir:: SwitchTargets ,
588
595
) {
589
596
let inactive_variants = match value {
590
- SwitchTargetValue :: Normal ( value ) => InactiveVariants :: Active ( data . next_discr ( value ) ) ,
597
+ SwitchTargetValue :: Normal ( variant_idx ) => InactiveVariants :: Active ( variant_idx ) ,
591
598
SwitchTargetValue :: Otherwise if self . include_inactive_in_otherwise => {
592
- InactiveVariants :: Inactives ( data. variants ( targets) )
599
+ InactiveVariants :: Inactives ( & data. targets )
593
600
}
594
601
_ => return ,
595
602
} ;
0 commit comments