@@ -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
@@ -451,25 +444,32 @@ impl<'tcx> Analysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
451444        & mut  self , 
452445        block :  mir:: BasicBlock , 
453446        discr :  & mir:: Operand < ' tcx > , 
447+         targets :  & mir:: SwitchTargets , 
454448    )  -> Option < Self :: SwitchIntData >  { 
455449        if  !self . tcx . sess . opts . unstable_opts . precise_enum_drop_elaboration  { 
456450            return  None ; 
457451        } 
458452
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 ( ) 
460461    } 
461462
462463    fn  apply_switch_int_edge_effect ( 
463464        & mut  self , 
464-         data :  & mut   Self :: SwitchIntData , 
465+         data :  & Self :: SwitchIntData , 
465466        state :  & mut  Self :: Domain , 
466467        value :  SwitchTargetValue , 
467-         targets :  & mir:: SwitchTargets , 
468468    )  { 
469469        let  inactive_variants = match  value { 
470-             SwitchTargetValue :: Normal ( value )  => InactiveVariants :: Active ( data . next_discr ( value ) ) , 
470+             SwitchTargetValue :: Normal ( variant_idx )  => InactiveVariants :: Active ( variant_idx ) , 
471471            SwitchTargetValue :: Otherwise  if  self . exclude_inactive_in_otherwise  => { 
472-                 InactiveVariants :: Inactives ( data. variants ( targets) ) 
472+                 InactiveVariants :: Inactives ( & data. targets ) 
473473            } 
474474            _ => return , 
475475        } ; 
@@ -567,6 +567,7 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
567567        & mut  self , 
568568        block :  mir:: BasicBlock , 
569569        discr :  & mir:: Operand < ' tcx > , 
570+         targets :  & mir:: SwitchTargets , 
570571    )  -> Option < Self :: SwitchIntData >  { 
571572        if  !self . tcx . sess . opts . unstable_opts . precise_enum_drop_elaboration  { 
572573            return  None ; 
@@ -576,20 +577,26 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
576577            return  None ; 
577578        } 
578579
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 ( ) 
580588    } 
581589
582590    fn  apply_switch_int_edge_effect ( 
583591        & mut  self , 
584-         data :  & mut   Self :: SwitchIntData , 
592+         data :  & Self :: SwitchIntData , 
585593        state :  & mut  Self :: Domain , 
586594        value :  SwitchTargetValue , 
587-         targets :  & mir:: SwitchTargets , 
588595    )  { 
589596        let  inactive_variants = match  value { 
590-             SwitchTargetValue :: Normal ( value )  => InactiveVariants :: Active ( data . next_discr ( value ) ) , 
597+             SwitchTargetValue :: Normal ( variant_idx )  => InactiveVariants :: Active ( variant_idx ) , 
591598            SwitchTargetValue :: Otherwise  if  self . include_inactive_in_otherwise  => { 
592-                 InactiveVariants :: Inactives ( data. variants ( targets) ) 
599+                 InactiveVariants :: Inactives ( & data. targets ) 
593600            } 
594601            _ => return , 
595602        } ; 
0 commit comments