5656use rustc_const_eval:: interpret:: { ImmTy , InterpCx , MemPlaceMeta , OpTy , Projectable , Scalar } ;
5757use rustc_data_structures:: fx:: { FxHashMap , FxIndexSet } ;
5858use rustc_data_structures:: graph:: dominators:: Dominators ;
59+ use rustc_hir:: def:: DefKind ;
5960use rustc_index:: bit_set:: BitSet ;
6061use rustc_index:: IndexVec ;
6162use rustc_macros:: newtype_index;
@@ -64,6 +65,7 @@ use rustc_middle::mir::visit::*;
6465use rustc_middle:: mir:: * ;
6566use rustc_middle:: ty:: layout:: LayoutOf ;
6667use rustc_middle:: ty:: { self , Ty , TyCtxt , TypeAndMut } ;
68+ use rustc_span:: def_id:: DefId ;
6769use rustc_span:: DUMMY_SP ;
6870use rustc_target:: abi:: { self , Abi , Size , VariantIdx , FIRST_VARIANT } ;
6971use std:: borrow:: Cow ;
@@ -129,6 +131,16 @@ newtype_index! {
129131 struct VnIndex { }
130132}
131133
134+ /// Computing the aggregate's type can be quite slow, so we only keep the minimal amount of
135+ /// information to reconstruct it when needed.
136+ #[ derive( Copy , Clone , Debug , PartialEq , Eq , Hash ) ]
137+ enum AggregateTy < ' tcx > {
138+ /// Invariant: this must not be used for an empty array.
139+ Array ,
140+ Tuple ,
141+ Def ( DefId , ty:: GenericArgsRef < ' tcx > ) ,
142+ }
143+
132144#[ derive( Copy , Clone , Debug , PartialEq , Eq , Hash ) ]
133145enum AddressKind {
134146 Ref ( BorrowKind ) ,
@@ -145,7 +157,7 @@ enum Value<'tcx> {
145157 Constant ( Const < ' tcx > ) ,
146158 /// An aggregate value, either tuple/closure/struct/enum.
147159 /// This does not contain unions, as we cannot reason with the value.
148- Aggregate ( Ty < ' tcx > , VariantIdx , Vec < VnIndex > ) ,
160+ Aggregate ( AggregateTy < ' tcx > , VariantIdx , Vec < VnIndex > ) ,
149161 /// This corresponds to a `[value; count]` expression.
150162 Repeat ( VnIndex , ty:: Const < ' tcx > ) ,
151163 /// The address of a place.
@@ -282,11 +294,23 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
282294 Repeat ( ..) => return None ,
283295
284296 Constant ( ref constant) => self . ecx . eval_mir_constant ( constant, None , None ) . ok ( ) ?,
285- Aggregate ( ty , variant, ref fields) => {
297+ Aggregate ( kind , variant, ref fields) => {
286298 let fields = fields
287299 . iter ( )
288300 . map ( |& f| self . evaluated [ f] . as_ref ( ) )
289301 . collect :: < Option < Vec < _ > > > ( ) ?;
302+ let ty = match kind {
303+ AggregateTy :: Array => {
304+ assert ! ( fields. len( ) > 0 ) ;
305+ Ty :: new_array ( self . tcx , fields[ 0 ] . layout . ty , fields. len ( ) as u64 )
306+ }
307+ AggregateTy :: Tuple => {
308+ Ty :: new_tup_from_iter ( self . tcx , fields. iter ( ) . map ( |f| f. layout . ty ) )
309+ }
310+ AggregateTy :: Def ( def_id, args) => {
311+ self . tcx . type_of ( def_id) . instantiate ( self . tcx , args)
312+ }
313+ } ;
290314 let variant = if ty. is_enum ( ) { Some ( variant) } else { None } ;
291315 let ty = self . ecx . layout_of ( ty) . ok ( ) ?;
292316 if ty. is_zst ( ) {
@@ -502,7 +526,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
502526 Value :: Repeat ( inner, _) => {
503527 return Some ( * inner) ;
504528 }
505- Value :: Aggregate ( ty , _, operands) if ty . is_array ( ) => {
529+ Value :: Aggregate ( AggregateTy :: Array , _, operands) => {
506530 let offset = if from_end {
507531 operands. len ( ) - offset as usize
508532 } else {
@@ -650,20 +674,30 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
650674 }
651675 Rvalue :: NullaryOp ( op, ty) => Value :: NullaryOp ( op, ty) ,
652676 Rvalue :: Aggregate ( box ref kind, ref mut fields) => {
653- let variant_index = match * kind {
654- AggregateKind :: Array ( ..)
655- | AggregateKind :: Tuple
656- | AggregateKind :: Closure ( ..)
657- | AggregateKind :: Generator ( ..) => FIRST_VARIANT ,
658- AggregateKind :: Adt ( _, variant_index, _, _, None ) => variant_index,
677+ let ( ty, variant_index) = match * kind {
678+ // For empty arrays, we have not mean to recover the type. They are ZSTs
679+ // anyway, so return them as such.
680+ AggregateKind :: Array ( ..) | AggregateKind :: Tuple if fields. is_empty ( ) => {
681+ return Some ( self . insert ( Value :: Constant ( Const :: zero_sized (
682+ rvalue. ty ( self . local_decls , self . tcx ) ,
683+ ) ) ) ) ;
684+ }
685+ AggregateKind :: Array ( ..) => ( AggregateTy :: Array , FIRST_VARIANT ) ,
686+ AggregateKind :: Tuple => ( AggregateTy :: Tuple , FIRST_VARIANT ) ,
687+ AggregateKind :: Closure ( did, substs)
688+ | AggregateKind :: Generator ( did, substs, _) => {
689+ ( AggregateTy :: Def ( did, substs) , FIRST_VARIANT )
690+ }
691+ AggregateKind :: Adt ( did, variant_index, substs, _, None ) => {
692+ ( AggregateTy :: Def ( did, substs) , variant_index)
693+ }
659694 // Do not track unions.
660695 AggregateKind :: Adt ( _, _, _, _, Some ( _) ) => return None ,
661696 } ;
662697 let fields: Option < Vec < _ > > = fields
663698 . iter_mut ( )
664699 . map ( |op| self . simplify_operand ( op, location) . or_else ( || self . new_opaque ( ) ) )
665700 . collect ( ) ;
666- let ty = rvalue. ty ( self . local_decls , self . tcx ) ;
667701 Value :: Aggregate ( ty, variant_index, fields?)
668702 }
669703 Rvalue :: Ref ( _, borrow_kind, ref mut place) => {
@@ -716,8 +750,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
716750
717751 fn simplify_discriminant ( & mut self , place : VnIndex ) -> Option < VnIndex > {
718752 if let Value :: Aggregate ( enum_ty, variant, _) = * self . get ( place)
719- && enum_ty. is_enum ( )
753+ && let AggregateTy :: Def ( enum_did, enum_substs) = enum_ty
754+ && let DefKind :: Enum = self . tcx . def_kind ( enum_did)
720755 {
756+ let enum_ty = self . tcx . type_of ( enum_did) . instantiate ( self . tcx , enum_substs) ;
721757 let discr = self . ecx . discriminant_for_variant ( enum_ty, variant) . ok ( ) ?;
722758 return Some ( self . insert_scalar ( discr. to_scalar ( ) , discr. layout . ty ) ) ;
723759 }
0 commit comments