@@ -668,9 +668,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
668
668
669
669
fn type_is_fat_ptr ( & self , ty : Ty < ' tcx > ) -> bool {
670
670
match ty. sty {
671
- ty:: TyRawPtr ( ty :: TypeAndMut { ty , .. } ) |
672
- ty:: TyRef ( _, ty :: TypeAndMut { ty , .. } ) |
673
- ty:: TyBox ( ty ) => !self . type_is_sized ( ty) ,
671
+ ty:: TyRawPtr ( ref tam ) |
672
+ ty:: TyRef ( _, ref tam ) => ! self . type_is_sized ( tam . ty ) ,
673
+ ty:: TyAdt ( def , _ ) if def . is_box ( ) => !self . type_is_sized ( ty. boxed_ty ( ) ) ,
674
674
_ => false ,
675
675
}
676
676
}
@@ -714,26 +714,27 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
714
714
715
715
Ok ( ( offset, ty) )
716
716
}
717
+ fn get_fat_field ( & self , pointee_ty : Ty < ' tcx > , field_index : usize ) -> EvalResult < ' tcx , Ty < ' tcx > > {
718
+ match ( field_index, & self . tcx . struct_tail ( pointee_ty) . sty ) {
719
+ ( 1 , & ty:: TyStr ) |
720
+ ( 1 , & ty:: TySlice ( _) ) => Ok ( self . tcx . types . usize ) ,
721
+ ( 1 , & ty:: TyDynamic ( ..) ) |
722
+ ( 0 , _) => Ok ( self . tcx . mk_imm_ptr ( self . tcx . types . u8 ) ) ,
723
+ _ => bug ! ( "invalid fat pointee type: {}" , pointee_ty) ,
724
+ }
725
+ }
717
726
718
727
pub fn get_field_ty ( & self , ty : Ty < ' tcx > , field_index : usize ) -> EvalResult < ' tcx , Ty < ' tcx > > {
719
728
match ty. sty {
729
+ ty:: TyAdt ( adt_def, _) if adt_def. is_box ( ) => self . get_fat_field ( ty. boxed_ty ( ) , field_index) ,
720
730
ty:: TyAdt ( adt_def, substs) => {
721
731
Ok ( adt_def. struct_variant ( ) . fields [ field_index] . ty ( self . tcx , substs) )
722
732
}
723
733
724
734
ty:: TyTuple ( fields) => Ok ( fields[ field_index] ) ,
725
735
726
- ty:: TyRef ( _, ty:: TypeAndMut { ty, .. } ) |
727
- ty:: TyRawPtr ( ty:: TypeAndMut { ty, .. } ) |
728
- ty:: TyBox ( ty) => {
729
- match ( field_index, & self . tcx . struct_tail ( ty) . sty ) {
730
- ( 1 , & ty:: TyStr ) |
731
- ( 1 , & ty:: TySlice ( _) ) => Ok ( self . tcx . types . usize ) ,
732
- ( 1 , & ty:: TyDynamic ( ..) ) |
733
- ( 0 , _) => Ok ( self . tcx . mk_imm_ptr ( self . tcx . types . u8 ) ) ,
734
- _ => bug ! ( "invalid fat pointee type: {}" , ty) ,
735
- }
736
- }
736
+ ty:: TyRef ( _, ref tam) |
737
+ ty:: TyRawPtr ( ref tam) => self . get_fat_field ( tam. ty , field_index) ,
737
738
_ => Err ( EvalError :: Unimplemented ( format ! ( "can't handle type: {:?}, {:?}" , ty, ty. sty) ) ) ,
738
739
}
739
740
}
@@ -1076,9 +1077,10 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
1076
1077
1077
1078
ty:: TyFnPtr ( _) => PrimValKind :: FnPtr ,
1078
1079
1079
- ty:: TyBox ( ty) |
1080
- ty:: TyRef ( _, ty:: TypeAndMut { ty, .. } ) |
1081
- ty:: TyRawPtr ( ty:: TypeAndMut { ty, .. } ) if self . type_is_sized ( ty) => PrimValKind :: Ptr ,
1080
+ ty:: TyRef ( _, ref tam) |
1081
+ ty:: TyRawPtr ( ref tam) if self . type_is_sized ( tam. ty ) => PrimValKind :: Ptr ,
1082
+
1083
+ ty:: TyAdt ( ref def, _) if def. is_box ( ) => PrimValKind :: Ptr ,
1082
1084
1083
1085
ty:: TyAdt ( ..) => {
1084
1086
use rustc:: ty:: layout:: Layout :: * ;
@@ -1132,6 +1134,23 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
1132
1134
}
1133
1135
}
1134
1136
1137
+ fn read_ptr ( & mut self , ptr : Pointer , pointee_ty : Ty < ' tcx > ) -> EvalResult < ' tcx , Value > {
1138
+ let p = self . memory . read_ptr ( ptr) ?;
1139
+ if self . type_is_sized ( pointee_ty) {
1140
+ Ok ( Value :: ByVal ( PrimVal :: Ptr ( p) ) )
1141
+ } else {
1142
+ trace ! ( "reading fat pointer extra of type {}" , pointee_ty) ;
1143
+ let extra = ptr. offset ( self . memory . pointer_size ( ) ) ;
1144
+ let extra = match self . tcx . struct_tail ( pointee_ty) . sty {
1145
+ ty:: TyDynamic ( ..) => PrimVal :: Ptr ( self . memory . read_ptr ( extra) ?) ,
1146
+ ty:: TySlice ( ..) |
1147
+ ty:: TyStr => PrimVal :: from_u128 ( self . memory . read_usize ( extra) ? as u128 ) ,
1148
+ _ => bug ! ( "unsized primval ptr read from {:?}" , pointee_ty) ,
1149
+ } ;
1150
+ Ok ( Value :: ByValPair ( PrimVal :: Ptr ( p) , extra) )
1151
+ }
1152
+ }
1153
+
1135
1154
fn try_read_value ( & mut self , ptr : Pointer , ty : Ty < ' tcx > ) -> EvalResult < ' tcx , Option < Value > > {
1136
1155
use syntax:: ast:: FloatTy ;
1137
1156
@@ -1175,26 +1194,13 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
1175
1194
ty:: TyFloat ( FloatTy :: F64 ) => PrimVal :: from_f64 ( self . memory . read_f64 ( ptr) ?) ,
1176
1195
1177
1196
ty:: TyFnPtr ( _) => self . memory . read_ptr ( ptr) . map ( PrimVal :: Ptr ) ?,
1178
- ty:: TyBox ( ty) |
1179
- ty:: TyRef ( _, ty:: TypeAndMut { ty, .. } ) |
1180
- ty:: TyRawPtr ( ty:: TypeAndMut { ty, .. } ) => {
1181
- let p = self . memory . read_ptr ( ptr) ?;
1182
- if self . type_is_sized ( ty) {
1183
- PrimVal :: Ptr ( p)
1184
- } else {
1185
- trace ! ( "reading fat pointer extra of type {}" , ty) ;
1186
- let extra = ptr. offset ( self . memory . pointer_size ( ) ) ;
1187
- let extra = match self . tcx . struct_tail ( ty) . sty {
1188
- ty:: TyDynamic ( ..) => PrimVal :: Ptr ( self . memory . read_ptr ( extra) ?) ,
1189
- ty:: TySlice ( ..) |
1190
- ty:: TyStr => PrimVal :: from_u128 ( self . memory . read_usize ( extra) ? as u128 ) ,
1191
- _ => bug ! ( "unsized primval ptr read from {:?}" , ty) ,
1192
- } ;
1193
- return Ok ( Some ( Value :: ByValPair ( PrimVal :: Ptr ( p) , extra) ) ) ;
1194
- }
1195
- }
1197
+ ty:: TyRef ( _, ref tam) |
1198
+ ty:: TyRawPtr ( ref tam) => return self . read_ptr ( ptr, tam. ty ) . map ( Some ) ,
1196
1199
1197
- ty:: TyAdt ( ..) => {
1200
+ ty:: TyAdt ( def, _) => {
1201
+ if def. is_box ( ) {
1202
+ return self . read_ptr ( ptr, ty. boxed_ty ( ) ) . map ( Some ) ;
1203
+ }
1198
1204
use rustc:: ty:: layout:: Layout :: * ;
1199
1205
if let CEnum { discr, signed, .. } = * self . type_layout ( ty) ? {
1200
1206
let size = discr. size ( ) . bytes ( ) ;
@@ -1230,6 +1236,45 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
1230
1236
self . frame ( ) . substs
1231
1237
}
1232
1238
1239
+ fn unsize_into_ptr (
1240
+ & mut self ,
1241
+ src : Value ,
1242
+ src_ty : Ty < ' tcx > ,
1243
+ dest : Lvalue < ' tcx > ,
1244
+ dest_ty : Ty < ' tcx > ,
1245
+ sty : Ty < ' tcx > ,
1246
+ dty : Ty < ' tcx > ,
1247
+ ) -> EvalResult < ' tcx , ( ) > {
1248
+ // A<Struct> -> A<Trait> conversion
1249
+ let ( src_pointee_ty, dest_pointee_ty) = self . tcx . struct_lockstep_tails ( sty, dty) ;
1250
+
1251
+ match ( & src_pointee_ty. sty , & dest_pointee_ty. sty ) {
1252
+ ( & ty:: TyArray ( _, length) , & ty:: TySlice ( _) ) => {
1253
+ let ptr = src. read_ptr ( & self . memory ) ?;
1254
+ let len = PrimVal :: from_u128 ( length as u128 ) ;
1255
+ let ptr = PrimVal :: Ptr ( ptr) ;
1256
+ self . write_value ( Value :: ByValPair ( ptr, len) , dest, dest_ty)
1257
+ }
1258
+ ( & ty:: TyDynamic ( ..) , & ty:: TyDynamic ( ..) ) => {
1259
+ // For now, upcasts are limited to changes in marker
1260
+ // traits, and hence never actually require an actual
1261
+ // change to the vtable.
1262
+ self . write_value ( src, dest, dest_ty)
1263
+ } ,
1264
+ ( _, & ty:: TyDynamic ( ref data, _) ) => {
1265
+ let trait_ref = data. principal ( ) . unwrap ( ) . with_self_ty ( self . tcx , src_pointee_ty) ;
1266
+ let trait_ref = self . tcx . erase_regions ( & trait_ref) ;
1267
+ let vtable = self . get_vtable ( trait_ref) ?;
1268
+ let ptr = src. read_ptr ( & self . memory ) ?;
1269
+ let ptr = PrimVal :: Ptr ( ptr) ;
1270
+ let extra = PrimVal :: Ptr ( vtable) ;
1271
+ self . write_value ( Value :: ByValPair ( ptr, extra) , dest, dest_ty)
1272
+ } ,
1273
+
1274
+ _ => bug ! ( "invalid unsizing {:?} -> {:?}" , src_ty, dest_ty) ,
1275
+ }
1276
+ }
1277
+
1233
1278
fn unsize_into (
1234
1279
& mut self ,
1235
1280
src : Value ,
@@ -1238,40 +1283,16 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
1238
1283
dest_ty : Ty < ' tcx > ,
1239
1284
) -> EvalResult < ' tcx , ( ) > {
1240
1285
match ( & src_ty. sty , & dest_ty. sty ) {
1241
- ( & ty:: TyBox ( sty) , & ty:: TyBox ( dty) ) |
1242
- ( & ty:: TyRef ( _, ty:: TypeAndMut { ty : sty, .. } ) , & ty:: TyRef ( _, ty:: TypeAndMut { ty : dty, .. } ) ) |
1243
- ( & ty:: TyRef ( _, ty:: TypeAndMut { ty : sty, .. } ) , & ty:: TyRawPtr ( ty:: TypeAndMut { ty : dty, .. } ) ) |
1244
- ( & ty:: TyRawPtr ( ty:: TypeAndMut { ty : sty, .. } ) , & ty:: TyRawPtr ( ty:: TypeAndMut { ty : dty, .. } ) ) => {
1245
- // A<Struct> -> A<Trait> conversion
1246
- let ( src_pointee_ty, dest_pointee_ty) = self . tcx . struct_lockstep_tails ( sty, dty) ;
1247
-
1248
- match ( & src_pointee_ty. sty , & dest_pointee_ty. sty ) {
1249
- ( & ty:: TyArray ( _, length) , & ty:: TySlice ( _) ) => {
1250
- let ptr = src. read_ptr ( & self . memory ) ?;
1251
- let len = PrimVal :: from_u128 ( length as u128 ) ;
1252
- let ptr = PrimVal :: Ptr ( ptr) ;
1253
- self . write_value ( Value :: ByValPair ( ptr, len) , dest, dest_ty) ?;
1286
+ ( & ty:: TyRef ( _, ref s) , & ty:: TyRef ( _, ref d) ) |
1287
+ ( & ty:: TyRef ( _, ref s) , & ty:: TyRawPtr ( ref d) ) |
1288
+ ( & ty:: TyRawPtr ( ref s) , & ty:: TyRawPtr ( ref d) ) => self . unsize_into_ptr ( src, src_ty, dest, dest_ty, s. ty , d. ty ) ,
1289
+ ( & ty:: TyAdt ( def_a, substs_a) , & ty:: TyAdt ( def_b, substs_b) ) => {
1290
+ if def_a. is_box ( ) || def_b. is_box ( ) {
1291
+ if !def_a. is_box ( ) || !def_b. is_box ( ) {
1292
+ panic ! ( "invalid unsizing between {:?} -> {:?}" , src_ty, dest_ty) ;
1254
1293
}
1255
- ( & ty:: TyDynamic ( ..) , & ty:: TyDynamic ( ..) ) => {
1256
- // For now, upcasts are limited to changes in marker
1257
- // traits, and hence never actually require an actual
1258
- // change to the vtable.
1259
- self . write_value ( src, dest, dest_ty) ?;
1260
- } ,
1261
- ( _, & ty:: TyDynamic ( ref data, _) ) => {
1262
- let trait_ref = data. principal ( ) . unwrap ( ) . with_self_ty ( self . tcx , src_pointee_ty) ;
1263
- let trait_ref = self . tcx . erase_regions ( & trait_ref) ;
1264
- let vtable = self . get_vtable ( trait_ref) ?;
1265
- let ptr = src. read_ptr ( & self . memory ) ?;
1266
- let ptr = PrimVal :: Ptr ( ptr) ;
1267
- let extra = PrimVal :: Ptr ( vtable) ;
1268
- self . write_value ( Value :: ByValPair ( ptr, extra) , dest, dest_ty) ?;
1269
- } ,
1270
-
1271
- _ => bug ! ( "invalid unsizing {:?} -> {:?}" , src_ty, dest_ty) ,
1294
+ return self . unsize_into_ptr ( src, src_ty, dest, dest_ty, src_ty. boxed_ty ( ) , dest_ty. boxed_ty ( ) ) ;
1272
1295
}
1273
- }
1274
- ( & ty:: TyAdt ( def_a, substs_a) , & ty:: TyAdt ( def_b, substs_b) ) => {
1275
1296
// FIXME(solson)
1276
1297
let dest = self . force_allocation ( dest) ?. to_ptr ( ) ;
1277
1298
// unsizing of generic struct with pointer fields
@@ -1307,10 +1328,10 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
1307
1328
self . unsize_into ( Value :: ByRef ( src_f_ptr) , src_fty, Lvalue :: from_ptr ( dst_f_ptr) , dst_fty) ?;
1308
1329
}
1309
1330
}
1331
+ Ok ( ( ) )
1310
1332
}
1311
1333
_ => bug ! ( "unsize_into: invalid conversion: {:?} -> {:?}" , src_ty, dest_ty) ,
1312
1334
}
1313
- Ok ( ( ) )
1314
1335
}
1315
1336
1316
1337
pub ( super ) fn dump_local ( & self , lvalue : Lvalue < ' tcx > ) {
0 commit comments