@@ -70,22 +70,6 @@ struct ConstAnalysis<'a, 'tcx> {
7070 param_env : ty:: ParamEnv < ' tcx > ,
7171}
7272
73- impl < ' tcx > ConstAnalysis < ' _ , ' tcx > {
74- fn eval_discriminant (
75- & self ,
76- enum_ty : Ty < ' tcx > ,
77- variant_index : VariantIdx ,
78- ) -> Option < ScalarTy < ' tcx > > {
79- if !enum_ty. is_enum ( ) {
80- return None ;
81- }
82- let discr = enum_ty. discriminant_for_variant ( self . tcx , variant_index) ?;
83- let discr_layout = self . tcx . layout_of ( self . param_env . and ( discr. ty ) ) . ok ( ) ?;
84- let discr_value = Scalar :: try_from_uint ( discr. val , discr_layout. size ) ?;
85- Some ( ScalarTy ( discr_value, discr. ty ) )
86- }
87- }
88-
8973impl < ' tcx > ValueAnalysis < ' tcx > for ConstAnalysis < ' _ , ' tcx > {
9074 type Value = FlatSet < ScalarTy < ' tcx > > ;
9175
@@ -126,59 +110,55 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
126110 // we must make sure that all `target as Variant#i` are `Top`.
127111 state. flood ( target. as_ref ( ) , self . map ( ) ) ;
128112
129- if let Some ( target_idx) = self . map ( ) . find ( target. as_ref ( ) ) {
130- let ( variant_target, variant_index) = match * * kind {
131- AggregateKind :: Tuple | AggregateKind :: Closure ( ..) => {
132- ( Some ( target_idx) , None )
133- }
134- AggregateKind :: Adt ( def_id, variant_index, ..) => {
135- match self . tcx . def_kind ( def_id) {
136- DefKind :: Struct => ( Some ( target_idx) , None ) ,
137- DefKind :: Enum => (
138- self . map . apply ( target_idx, TrackElem :: Variant ( variant_index) ) ,
139- Some ( variant_index) ,
140- ) ,
141- _ => ( None , None ) ,
142- }
143- }
144- _ => ( None , None ) ,
145- } ;
146- if let Some ( variant_target_idx) = variant_target {
147- for ( field_index, operand) in operands. iter ( ) . enumerate ( ) {
148- if let Some ( field) = self . map ( ) . apply (
149- variant_target_idx,
150- TrackElem :: Field ( FieldIdx :: from_usize ( field_index) ) ,
151- ) {
152- let result = self . handle_operand ( operand, state) ;
153- state. insert_idx ( field, result, self . map ( ) ) ;
154- }
113+ let Some ( target_idx) = self . map ( ) . find ( target. as_ref ( ) ) else { return } ;
114+
115+ let ( variant_target, variant_index) = match * * kind {
116+ AggregateKind :: Tuple | AggregateKind :: Closure ( ..) => ( Some ( target_idx) , None ) ,
117+ AggregateKind :: Adt ( def_id, variant_index, ..) => {
118+ match self . tcx . def_kind ( def_id) {
119+ DefKind :: Struct => ( Some ( target_idx) , None ) ,
120+ DefKind :: Enum => (
121+ self . map . apply ( target_idx, TrackElem :: Variant ( variant_index) ) ,
122+ Some ( variant_index) ,
123+ ) ,
124+ _ => return ,
155125 }
156126 }
157- if let Some ( variant_index) = variant_index
158- && let Some ( discr_idx) = self . map ( ) . apply ( target_idx, TrackElem :: Discriminant )
159- {
160- // We are assigning the discriminant as part of an aggregate.
161- // This discriminant can only alias a variant field's value if the operand
162- // had an invalid value for that type.
163- // Using invalid values is UB, so we are allowed to perform the assignment
164- // without extra flooding.
165- let enum_ty = target. ty ( self . local_decls , self . tcx ) . ty ;
166- if let Some ( discr_val) = self . eval_discriminant ( enum_ty, variant_index) {
167- state. insert_value_idx ( discr_idx, FlatSet :: Elem ( discr_val) , & self . map ) ;
127+ _ => return ,
128+ } ;
129+ if let Some ( variant_target_idx) = variant_target {
130+ for ( field_index, operand) in operands. iter ( ) . enumerate ( ) {
131+ if let Some ( field) = self . map ( ) . apply (
132+ variant_target_idx,
133+ TrackElem :: Field ( FieldIdx :: from_usize ( field_index) ) ,
134+ ) {
135+ let result = self . handle_operand ( operand, state) ;
136+ state. insert_idx ( field, result, self . map ( ) ) ;
168137 }
169138 }
170139 }
140+ if let Some ( variant_index) = variant_index
141+ && let Some ( discr_idx) = self . map ( ) . apply ( target_idx, TrackElem :: Discriminant )
142+ {
143+ // We are assigning the discriminant as part of an aggregate.
144+ // This discriminant can only alias a variant field's value if the operand
145+ // had an invalid value for that type.
146+ // Using invalid values is UB, so we are allowed to perform the assignment
147+ // without extra flooding.
148+ let enum_ty = target. ty ( self . local_decls , self . tcx ) . ty ;
149+ if let Some ( discr_val) = self . eval_discriminant ( enum_ty, variant_index) {
150+ state. insert_value_idx ( discr_idx, FlatSet :: Elem ( discr_val) , & self . map ) ;
151+ }
152+ }
171153 }
172154 Rvalue :: CheckedBinaryOp ( op, box ( left, right) ) => {
173155 // Flood everything now, so we can use `insert_value_idx` directly later.
174156 state. flood ( target. as_ref ( ) , self . map ( ) ) ;
175157
176- let target = self . map ( ) . find ( target. as_ref ( ) ) ;
158+ let Some ( target) = self . map ( ) . find ( target. as_ref ( ) ) else { return } ;
177159
178- let value_target = target
179- . and_then ( |target| self . map ( ) . apply ( target, TrackElem :: Field ( 0_u32 . into ( ) ) ) ) ;
180- let overflow_target = target
181- . and_then ( |target| self . map ( ) . apply ( target, TrackElem :: Field ( 1_u32 . into ( ) ) ) ) ;
160+ let value_target = self . map ( ) . apply ( target, TrackElem :: Field ( 0_u32 . into ( ) ) ) ;
161+ let overflow_target = self . map ( ) . apply ( target, TrackElem :: Field ( 1_u32 . into ( ) ) ) ;
182162
183163 if value_target. is_some ( ) || overflow_target. is_some ( ) {
184164 let ( val, overflow) = self . binary_op ( state, * op, left, right) ;
@@ -377,6 +357,20 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
377357 }
378358 }
379359
360+ fn eval_discriminant (
361+ & self ,
362+ enum_ty : Ty < ' tcx > ,
363+ variant_index : VariantIdx ,
364+ ) -> Option < ScalarTy < ' tcx > > {
365+ if !enum_ty. is_enum ( ) {
366+ return None ;
367+ }
368+ let discr = enum_ty. discriminant_for_variant ( self . tcx , variant_index) ?;
369+ let discr_layout = self . tcx . layout_of ( self . param_env . and ( discr. ty ) ) . ok ( ) ?;
370+ let discr_value = Scalar :: try_from_uint ( discr. val , discr_layout. size ) ?;
371+ Some ( ScalarTy ( discr_value, discr. ty ) )
372+ }
373+
380374 fn wrap_scalar ( & self , scalar : Scalar , ty : Ty < ' tcx > ) -> FlatSet < ScalarTy < ' tcx > > {
381375 FlatSet :: Elem ( ScalarTy ( scalar, ty) )
382376 }
@@ -520,21 +514,6 @@ impl<'tcx, 'map, 'a> Visitor<'tcx> for OperandCollector<'tcx, 'map, 'a> {
520514 _ => ( ) ,
521515 }
522516 }
523-
524- fn visit_rvalue ( & mut self , rvalue : & Rvalue < ' tcx > , location : Location ) {
525- match rvalue {
526- Rvalue :: Discriminant ( place) => {
527- match self . state . get_discr ( place. as_ref ( ) , self . visitor . map ) {
528- FlatSet :: Top => ( ) ,
529- FlatSet :: Elem ( value) => {
530- self . visitor . before_effect . insert ( ( location, * place) , value) ;
531- }
532- FlatSet :: Bottom => ( ) ,
533- }
534- }
535- _ => self . super_rvalue ( rvalue, location) ,
536- }
537- }
538517}
539518
540519struct DummyMachine ;
0 commit comments