@@ -7,9 +7,7 @@ use rustc_middle::bug;
77use  rustc_middle:: mir:: { 
88    self ,  Body ,  CallReturnPlaces ,  Location ,  SwitchTargetValue ,  TerminatorEdges , 
99} ; 
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 } ; 
1311use  tracing:: { debug,  instrument} ; 
1412
1513use  crate :: drop_flag_effects:: { DropFlagState ,  InactiveVariants } ; 
@@ -22,30 +20,25 @@ use crate::{
2220// Used by both `MaybeInitializedPlaces` and `MaybeUninitializedPlaces`. 
2321pub  struct  MaybePlacesSwitchIntData < ' tcx >  { 
2422    enum_place :  mir:: Place < ' tcx > , 
25-     discriminants :  Vec < ( VariantIdx ,  Discr < ' tcx > ) > , 
26-     index :  usize , 
23+     targets :  Vec < ( VariantIdx ,  mir:: BasicBlock ) > , 
2724} 
2825
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+     } ) ) 
4942} 
5043
5144impl < ' tcx >  MaybePlacesSwitchIntData < ' tcx >  { 
@@ -54,6 +47,7 @@ impl<'tcx> MaybePlacesSwitchIntData<'tcx> {
5447        body :  & Body < ' tcx > , 
5548        block :  mir:: BasicBlock , 
5649        discr :  & mir:: Operand < ' tcx > , 
50+         targets :  & mir:: SwitchTargets , 
5751    )  -> Option < Self >  { 
5852        let  Some ( discr)  = discr. place ( )  else  {  return  None  } ; 
5953
@@ -78,8 +72,7 @@ impl<'tcx> MaybePlacesSwitchIntData<'tcx> {
7872                        ty:: Adt ( enum_def,  _)  => { 
7973                            return  Some ( MaybePlacesSwitchIntData  { 
8074                                enum_place, 
81-                                 discriminants :  enum_def. discriminants ( tcx) . collect ( ) , 
82-                                 index :  0 , 
75+                                 targets :  collect_switch_targets ( * enum_def,  targets,  tcx) , 
8376                            } ) ; 
8477                        } 
8578
@@ -448,25 +441,32 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
448441        & mut  self , 
449442        block :  mir:: BasicBlock , 
450443        discr :  & mir:: Operand < ' tcx > , 
444+         targets :  & mir:: SwitchTargets , 
451445    )  -> Option < Self :: SwitchIntData >  { 
452446        if  !self . tcx . sess . opts . unstable_opts . precise_enum_drop_elaboration  { 
453447            return  None ; 
454448        } 
455449
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 ( ) 
457458    } 
458459
459460    fn  apply_switch_int_edge_effect ( 
460461        & mut  self , 
461-         data :  & mut   Self :: SwitchIntData , 
462+         data :  & Self :: SwitchIntData , 
462463        state :  & mut  Self :: Domain , 
463464        value :  SwitchTargetValue , 
464-         targets :  & mir:: SwitchTargets , 
465465    )  { 
466466        let  inactive_variants = match  value { 
467-             SwitchTargetValue :: Normal ( value )  => InactiveVariants :: Active ( data . next_discr ( value ) ) , 
467+             SwitchTargetValue :: Normal ( variant_idx )  => InactiveVariants :: Active ( variant_idx ) , 
468468            SwitchTargetValue :: Otherwise  if  self . exclude_inactive_in_otherwise  => { 
469-                 InactiveVariants :: Inactives ( data. variants ( targets) ) 
469+                 InactiveVariants :: Inactives ( & data. targets ) 
470470            } 
471471            _ => return , 
472472        } ; 
@@ -564,6 +564,7 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
564564        & mut  self , 
565565        block :  mir:: BasicBlock , 
566566        discr :  & mir:: Operand < ' tcx > , 
567+         targets :  & mir:: SwitchTargets , 
567568    )  -> Option < Self :: SwitchIntData >  { 
568569        if  !self . tcx . sess . opts . unstable_opts . precise_enum_drop_elaboration  { 
569570            return  None ; 
@@ -573,20 +574,26 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
573574            return  None ; 
574575        } 
575576
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 ( ) 
577585    } 
578586
579587    fn  apply_switch_int_edge_effect ( 
580588        & mut  self , 
581-         data :  & mut   Self :: SwitchIntData , 
589+         data :  & Self :: SwitchIntData , 
582590        state :  & mut  Self :: Domain , 
583591        value :  SwitchTargetValue , 
584-         targets :  & mir:: SwitchTargets , 
585592    )  { 
586593        let  inactive_variants = match  value { 
587-             SwitchTargetValue :: Normal ( value )  => InactiveVariants :: Active ( data . next_discr ( value ) ) , 
594+             SwitchTargetValue :: Normal ( variant_idx )  => InactiveVariants :: Active ( variant_idx ) , 
588595            SwitchTargetValue :: Otherwise  if  self . include_inactive_in_otherwise  => { 
589-                 InactiveVariants :: Inactives ( data. variants ( targets) ) 
596+                 InactiveVariants :: Inactives ( & data. targets ) 
590597            } 
591598            _ => return , 
592599        } ; 
0 commit comments