@@ -163,12 +163,6 @@ enum AggregateTy<'tcx> {
163163 Array ,
164164 Tuple ,
165165 Def ( DefId , ty:: GenericArgsRef < ' tcx > ) ,
166- RawPtr {
167- /// Needed for cast propagation.
168- data_pointer_ty : Ty < ' tcx > ,
169- /// The data pointer can be anything thin, so doesn't determine the output.
170- output_pointer_ty : Ty < ' tcx > ,
171- } ,
172166}
173167
174168#[ derive( Copy , Clone , Debug , PartialEq , Eq , Hash ) ]
@@ -194,6 +188,17 @@ enum Value<'tcx> {
194188 /// An aggregate value, either tuple/closure/struct/enum.
195189 /// This does not contain unions, as we cannot reason with the value.
196190 Aggregate ( AggregateTy < ' tcx > , VariantIdx , Vec < VnIndex > ) ,
191+ /// A raw pointer aggregate built from a thin pointer and metadata.
192+ RawPtr {
193+ /// Thin pointer component. This is field 0 in MIR.
194+ pointer : VnIndex ,
195+ /// Metadata component. This is field 1 in MIR.
196+ metadata : VnIndex ,
197+ /// Needed for cast propagation.
198+ data_pointer_ty : Ty < ' tcx > ,
199+ /// The data pointer can be anything thin, so doesn't determine the output.
200+ output_pointer_ty : Ty < ' tcx > ,
201+ } ,
197202 /// This corresponds to a `[value; count]` expression.
198203 Repeat ( VnIndex , ty:: Const < ' tcx > ) ,
199204 /// The address of a place.
@@ -402,22 +407,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
402407 AggregateTy :: Def ( def_id, args) => {
403408 self . tcx . type_of ( def_id) . instantiate ( self . tcx , args)
404409 }
405- AggregateTy :: RawPtr { output_pointer_ty, .. } => output_pointer_ty,
406410 } ;
407411 let variant = if ty. is_enum ( ) { Some ( variant) } else { None } ;
408412 let ty = self . ecx . layout_of ( ty) . ok ( ) ?;
409413 if ty. is_zst ( ) {
410414 ImmTy :: uninit ( ty) . into ( )
411- } else if matches ! ( kind, AggregateTy :: RawPtr { .. } ) {
412- // Pointers don't have fields, so don't `project_field` them.
413- let data = self . ecx . read_pointer ( fields[ 0 ] ) . discard_err ( ) ?;
414- let meta = if fields[ 1 ] . layout . is_zst ( ) {
415- MemPlaceMeta :: None
416- } else {
417- MemPlaceMeta :: Meta ( self . ecx . read_scalar ( fields[ 1 ] ) . discard_err ( ) ?)
418- } ;
419- let ptr_imm = Immediate :: new_pointer_with_meta ( data, meta, & self . ecx ) ;
420- ImmTy :: from_immediate ( ptr_imm, ty) . into ( )
421415 } else if matches ! (
422416 ty. backend_repr,
423417 BackendRepr :: Scalar ( ..) | BackendRepr :: ScalarPair ( ..)
@@ -446,6 +440,22 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
446440 return None ;
447441 }
448442 }
443+ RawPtr { pointer, metadata, output_pointer_ty, data_pointer_ty : _ } => {
444+ let pointer = self . evaluated [ pointer] . as_ref ( ) ?;
445+ let metadata = self . evaluated [ metadata] . as_ref ( ) ?;
446+ let output_pointer_ty = self . ecx . layout_of ( output_pointer_ty) . ok ( ) ?;
447+ debug_assert ! ( !output_pointer_ty. is_zst( ) ) ;
448+
449+ // Pointers don't have fields, so don't `project_field` them.
450+ let data = self . ecx . read_pointer ( pointer) . discard_err ( ) ?;
451+ let meta = if metadata. layout . is_zst ( ) {
452+ MemPlaceMeta :: None
453+ } else {
454+ MemPlaceMeta :: Meta ( self . ecx . read_scalar ( metadata) . discard_err ( ) ?)
455+ } ;
456+ let ptr_imm = Immediate :: new_pointer_with_meta ( data, meta, & self . ecx ) ;
457+ ImmTy :: from_immediate ( ptr_imm, output_pointer_ty) . into ( )
458+ }
449459
450460 Projection ( base, elem) => {
451461 let value = self . evaluated [ base] . as_ref ( ) ?;
@@ -1026,7 +1036,12 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
10261036 }
10271037 }
10281038
1029- let ( mut ty, variant_index) = match * kind {
1039+ let fields: Vec < _ > = field_ops
1040+ . iter_mut ( )
1041+ . map ( |op| self . simplify_operand ( op, location) . unwrap_or_else ( || self . new_opaque ( ) ) )
1042+ . collect ( ) ;
1043+
1044+ let ( ty, variant_index) = match * kind {
10301045 AggregateKind :: Array ( ..) => {
10311046 assert ! ( !field_ops. is_empty( ) ) ;
10321047 ( AggregateTy :: Array , FIRST_VARIANT )
@@ -1045,41 +1060,41 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
10451060 AggregateKind :: Adt ( _, _, _, _, Some ( _) ) => return None ,
10461061 AggregateKind :: RawPtr ( pointee_ty, mtbl) => {
10471062 assert_eq ! ( field_ops. len( ) , 2 ) ;
1048- let data_pointer_ty = field_ops[ FieldIdx :: ZERO ] . ty ( self . local_decls , self . tcx ) ;
1063+ let mut data_pointer_ty = field_ops[ FieldIdx :: ZERO ] . ty ( self . local_decls , self . tcx ) ;
10491064 let output_pointer_ty = Ty :: new_ptr ( self . tcx , pointee_ty, mtbl) ;
1050- ( AggregateTy :: RawPtr { data_pointer_ty, output_pointer_ty } , FIRST_VARIANT )
1051- }
1052- } ;
1053-
1054- let mut fields: Vec < _ > = field_ops
1055- . iter_mut ( )
1056- . map ( |op| self . simplify_operand ( op, location) . unwrap_or_else ( || self . new_opaque ( ) ) )
1057- . collect ( ) ;
10581065
1059- if let AggregateTy :: RawPtr { data_pointer_ty, output_pointer_ty } = & mut ty {
1060- let mut was_updated = false ;
1066+ let [ mut pointer, metadata] = fields. try_into ( ) . unwrap ( ) ;
1067+
1068+ // Any thin pointer of matching mutability is fine as the data pointer.
1069+ let mut was_updated = false ;
1070+ while let Value :: Cast {
1071+ kind : CastKind :: PtrToPtr ,
1072+ value : cast_value,
1073+ from : cast_from,
1074+ to : _,
1075+ } = self . get ( pointer)
1076+ && let ty:: RawPtr ( from_pointee_ty, from_mtbl) = cast_from. kind ( )
1077+ && let ty:: RawPtr ( _, output_mtbl) = output_pointer_ty. kind ( )
1078+ && from_mtbl == output_mtbl
1079+ && from_pointee_ty. is_sized ( self . tcx , self . typing_env ( ) )
1080+ {
1081+ pointer = * cast_value;
1082+ data_pointer_ty = * cast_from;
1083+ was_updated = true ;
1084+ }
10611085
1062- // Any thin pointer of matching mutability is fine as the data pointer.
1063- while let Value :: Cast {
1064- kind : CastKind :: PtrToPtr ,
1065- value : cast_value,
1066- from : cast_from,
1067- to : _,
1068- } = self . get ( fields[ 0 ] )
1069- && let ty:: RawPtr ( from_pointee_ty, from_mtbl) = cast_from. kind ( )
1070- && let ty:: RawPtr ( _, output_mtbl) = output_pointer_ty. kind ( )
1071- && from_mtbl == output_mtbl
1072- && from_pointee_ty. is_sized ( self . tcx , self . typing_env ( ) )
1073- {
1074- fields[ 0 ] = * cast_value;
1075- * data_pointer_ty = * cast_from;
1076- was_updated = true ;
1077- }
1086+ if was_updated && let Some ( op) = self . try_as_operand ( pointer, location) {
1087+ field_ops[ FieldIdx :: ZERO ] = op;
1088+ }
10781089
1079- if was_updated && let Some ( op) = self . try_as_operand ( fields[ 0 ] , location) {
1080- field_ops[ FieldIdx :: ZERO ] = op;
1090+ return Some ( self . insert ( Value :: RawPtr {
1091+ output_pointer_ty,
1092+ data_pointer_ty,
1093+ pointer,
1094+ metadata,
1095+ } ) ) ;
10811096 }
1082- }
1097+ } ;
10831098
10841099 if let AggregateTy :: Array = ty
10851100 && fields. len ( ) > 4
@@ -1165,9 +1180,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
11651180 ( UnOp :: Not , Value :: BinaryOp ( BinOp :: Ne , lhs, rhs) ) => {
11661181 Value :: BinaryOp ( BinOp :: Eq , * lhs, * rhs)
11671182 }
1168- ( UnOp :: PtrMetadata , Value :: Aggregate ( AggregateTy :: RawPtr { .. } , _, fields) ) => {
1169- return Some ( fields[ 1 ] ) ;
1170- }
1183+ ( UnOp :: PtrMetadata , Value :: RawPtr { metadata, .. } ) => return Some ( * metadata) ,
11711184 // We have an unsizing cast, which assigns the length to wide pointer metadata.
11721185 (
11731186 UnOp :: PtrMetadata ,
@@ -1399,16 +1412,15 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
13991412 // If a cast just casts away the metadata again, then we can get it by
14001413 // casting the original thin pointer passed to `from_raw_parts`
14011414 if let PtrToPtr = kind
1402- && let Value :: Aggregate ( AggregateTy :: RawPtr { data_pointer_ty, .. } , _, fields) =
1403- self . get ( value)
1415+ && let Value :: RawPtr { data_pointer_ty, pointer, .. } = self . get ( value)
14041416 && let ty:: RawPtr ( to_pointee, _) = to. kind ( )
14051417 && to_pointee. is_sized ( self . tcx , self . typing_env ( ) )
14061418 {
14071419 from = * data_pointer_ty;
1408- value = fields [ 0 ] ;
1420+ value = * pointer ;
14091421 was_updated_this_iteration = true ;
14101422 if * data_pointer_ty == to {
1411- return Some ( fields [ 0 ] ) ;
1423+ return Some ( * pointer ) ;
14121424 }
14131425 }
14141426
0 commit comments