@@ -267,25 +267,33 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
267
267
ty. is_sized ( self . tcx , & self . tcx . empty_parameter_environment ( ) , DUMMY_SP )
268
268
}
269
269
270
- pub fn load_mir ( & self , def_id : DefId ) -> CachedMir < ' a , ' tcx > {
270
+ pub fn load_mir ( & self , def_id : DefId ) -> EvalResult < ' tcx , CachedMir < ' a , ' tcx > > {
271
+ trace ! ( "load mir {:?}" , def_id) ;
271
272
if def_id. is_local ( ) {
272
- CachedMir :: Ref ( self . mir_map . map . get ( & def_id) . unwrap ( ) )
273
+ Ok ( CachedMir :: Ref ( self . mir_map . map . get ( & def_id) . unwrap ( ) ) )
273
274
} else {
274
275
let mut mir_cache = self . mir_cache . borrow_mut ( ) ;
275
276
if let Some ( mir) = mir_cache. get ( & def_id) {
276
- return CachedMir :: Owned ( mir. clone ( ) ) ;
277
+ return Ok ( CachedMir :: Owned ( mir. clone ( ) ) ) ;
277
278
}
278
279
279
280
let cs = & self . tcx . sess . cstore ;
280
- let mir = cs. maybe_get_item_mir ( self . tcx , def_id) . unwrap_or_else ( || {
281
- panic ! ( "no mir for `{}`" , self . tcx. item_path_str( def_id) ) ;
282
- } ) ;
283
- let cached = Rc :: new ( mir) ;
284
- mir_cache. insert ( def_id, cached. clone ( ) ) ;
285
- CachedMir :: Owned ( cached)
281
+ match cs. maybe_get_item_mir ( self . tcx , def_id) {
282
+ Some ( mir) => {
283
+ let cached = Rc :: new ( mir) ;
284
+ mir_cache. insert ( def_id, cached. clone ( ) ) ;
285
+ Ok ( CachedMir :: Owned ( cached) )
286
+ } ,
287
+ None => Err ( EvalError :: NoMirFor ( self . tcx . item_path_str ( def_id) ) ) ,
288
+ }
286
289
}
287
290
}
288
291
292
+ pub fn monomorphize_field_ty ( & self , f : ty:: FieldDef < ' tcx > , substs : & ' tcx Substs < ' tcx > ) -> Ty < ' tcx > {
293
+ let substituted = & f. ty ( self . tcx , substs) ;
294
+ self . tcx . normalize_associated_type ( & substituted)
295
+ }
296
+
289
297
pub fn monomorphize ( & self , ty : Ty < ' tcx > , substs : & ' tcx Substs < ' tcx > ) -> Ty < ' tcx > {
290
298
let substituted = ty. subst ( self . tcx , substs) ;
291
299
self . tcx . normalize_associated_type ( & substituted)
@@ -519,7 +527,10 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
519
527
. chain ( nonnull. offset_after_field . iter ( ) . map ( |s| s. bytes ( ) ) ) ;
520
528
try!( self . assign_fields ( dest, offsets, operands) ) ;
521
529
} else {
522
- assert_eq ! ( operands. len( ) , 0 ) ;
530
+ for operand in operands {
531
+ let operand_ty = self . operand_ty ( operand) ;
532
+ assert_eq ! ( self . type_size( operand_ty) , 0 ) ;
533
+ }
523
534
let offset = self . nonnull_offset ( dest_ty, nndiscr, discrfield) ?;
524
535
let dest = dest. offset ( offset. bytes ( ) as isize ) ;
525
536
try!( self . memory . write_isize ( dest, 0 ) ) ;
@@ -596,56 +607,19 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
596
607
self . memory . write_ptr ( dest, ptr) ?;
597
608
}
598
609
599
- Cast ( kind, ref operand, dest_ty) => {
610
+ Cast ( kind, ref operand, cast_ty) => {
611
+ debug_assert_eq ! ( self . monomorphize( cast_ty, self . substs( ) ) , dest_ty) ;
600
612
use rustc:: mir:: repr:: CastKind :: * ;
601
613
match kind {
602
614
Unsize => {
603
615
let src = self . eval_operand ( operand) ?;
604
616
let src_ty = self . operand_ty ( operand) ;
605
- let dest_ty = self . monomorphize ( dest_ty, self . substs ( ) ) ;
606
- // FIXME: cases where dest_ty is not a fat pointer. e.g. Arc<Struct> -> Arc<Trait>
607
- assert ! ( self . type_is_fat_ptr( dest_ty) ) ;
608
- let src_pointee_ty = pointee_type ( src_ty) . unwrap ( ) ;
609
- let dest_pointee_ty = pointee_type ( dest_ty) . unwrap ( ) ;
610
-
611
- // A<Struct> -> A<Trait> conversion
612
- let ( src_pointee_ty, dest_pointee_ty) = self . tcx . struct_lockstep_tails ( src_pointee_ty, dest_pointee_ty) ;
613
-
614
- match ( & src_pointee_ty. sty , & dest_pointee_ty. sty ) {
615
- ( & ty:: TyArray ( _, length) , & ty:: TySlice ( _) ) => {
616
- let ptr = src. read_ptr ( & self . memory ) ?;
617
- self . memory . write_ptr ( dest, ptr) ?;
618
- let ptr_size = self . memory . pointer_size ( ) as isize ;
619
- let dest_extra = dest. offset ( ptr_size) ;
620
- self . memory . write_usize ( dest_extra, length as u64 ) ?;
621
- }
622
- ( & ty:: TyTrait ( _) , & ty:: TyTrait ( _) ) => {
623
- // For now, upcasts are limited to changes in marker
624
- // traits, and hence never actually require an actual
625
- // change to the vtable.
626
- self . write_value ( src, dest, dest_ty) ?;
627
- } ,
628
- ( _, & ty:: TyTrait ( ref data) ) => {
629
- let trait_ref = data. principal . with_self_ty ( self . tcx , src_pointee_ty) ;
630
- let trait_ref = self . tcx . erase_regions ( & trait_ref) ;
631
- let vtable = self . get_vtable ( trait_ref) ?;
632
- let ptr = src. read_ptr ( & self . memory ) ?;
633
-
634
- self . memory . write_ptr ( dest, ptr) ?;
635
- let ptr_size = self . memory . pointer_size ( ) as isize ;
636
- let dest_extra = dest. offset ( ptr_size) ;
637
- self . memory . write_ptr ( dest_extra, vtable) ?;
638
- } ,
639
-
640
- _ => bug ! ( "invalid unsizing {:?} -> {:?}" , src_ty, dest_ty) ,
641
- }
617
+ self . unsize_into ( src, src_ty, dest, dest_ty) ?;
642
618
}
643
619
644
620
Misc => {
645
621
let src = self . eval_operand ( operand) ?;
646
622
let src_ty = self . operand_ty ( operand) ;
647
- // FIXME: dest_ty should already be monomorphized
648
- let dest_ty = self . monomorphize ( dest_ty, self . substs ( ) ) ;
649
623
if self . type_is_fat_ptr ( src_ty) {
650
624
trace ! ( "misc cast: {:?}" , src) ;
651
625
let ptr_size = self . memory . pointer_size ( ) ;
@@ -760,9 +734,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
760
734
761
735
use rustc:: ty:: layout:: Layout :: * ;
762
736
match * layout {
763
- Univariant { .. } => {
764
- assert_eq ! ( field_index, 0 ) ;
765
- Ok ( Size :: from_bytes ( 0 ) )
737
+ Univariant { ref variant, .. } => {
738
+ Ok ( variant. field_offset ( field_index) )
766
739
}
767
740
FatPointer { .. } => {
768
741
let bytes = layout:: FAT_PTR_ADDR * self . memory . pointer_size ( ) ;
@@ -1106,16 +1079,91 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
1106
1079
fn substs ( & self ) -> & ' tcx Substs < ' tcx > {
1107
1080
self . frame ( ) . substs
1108
1081
}
1109
- }
1110
1082
1111
- fn pointee_type ( ptr_ty : ty:: Ty ) -> Option < ty:: Ty > {
1112
- match ptr_ty. sty {
1113
- ty:: TyRef ( _, ty:: TypeAndMut { ty, .. } ) |
1114
- ty:: TyRawPtr ( ty:: TypeAndMut { ty, .. } ) |
1115
- ty:: TyBox ( ty) => {
1116
- Some ( ty)
1083
+ fn unsize_into (
1084
+ & mut self ,
1085
+ src : Value ,
1086
+ src_ty : Ty < ' tcx > ,
1087
+ dest : Pointer ,
1088
+ dest_ty : Ty < ' tcx > ,
1089
+ ) -> EvalResult < ' tcx , ( ) > {
1090
+ match ( & src_ty. sty , & dest_ty. sty ) {
1091
+ ( & ty:: TyBox ( sty) , & ty:: TyBox ( dty) ) |
1092
+ ( & ty:: TyRef ( _, ty:: TypeAndMut { ty : sty, .. } ) , & ty:: TyRef ( _, ty:: TypeAndMut { ty : dty, .. } ) ) |
1093
+ ( & ty:: TyRef ( _, ty:: TypeAndMut { ty : sty, .. } ) , & ty:: TyRawPtr ( ty:: TypeAndMut { ty : dty, .. } ) ) |
1094
+ ( & ty:: TyRawPtr ( ty:: TypeAndMut { ty : sty, .. } ) , & ty:: TyRawPtr ( ty:: TypeAndMut { ty : dty, .. } ) ) => {
1095
+ // A<Struct> -> A<Trait> conversion
1096
+ let ( src_pointee_ty, dest_pointee_ty) = self . tcx . struct_lockstep_tails ( sty, dty) ;
1097
+
1098
+ match ( & src_pointee_ty. sty , & dest_pointee_ty. sty ) {
1099
+ ( & ty:: TyArray ( _, length) , & ty:: TySlice ( _) ) => {
1100
+ let ptr = src. read_ptr ( & self . memory ) ?;
1101
+ self . memory . write_ptr ( dest, ptr) ?;
1102
+ let ptr_size = self . memory . pointer_size ( ) as isize ;
1103
+ let dest_extra = dest. offset ( ptr_size) ;
1104
+ self . memory . write_usize ( dest_extra, length as u64 ) ?;
1105
+ }
1106
+ ( & ty:: TyTrait ( _) , & ty:: TyTrait ( _) ) => {
1107
+ // For now, upcasts are limited to changes in marker
1108
+ // traits, and hence never actually require an actual
1109
+ // change to the vtable.
1110
+ self . write_value ( src, dest, dest_ty) ?;
1111
+ } ,
1112
+ ( _, & ty:: TyTrait ( ref data) ) => {
1113
+ let trait_ref = data. principal . with_self_ty ( self . tcx , src_pointee_ty) ;
1114
+ let trait_ref = self . tcx . erase_regions ( & trait_ref) ;
1115
+ let vtable = self . get_vtable ( trait_ref) ?;
1116
+ let ptr = src. read_ptr ( & self . memory ) ?;
1117
+
1118
+ self . memory . write_ptr ( dest, ptr) ?;
1119
+ let ptr_size = self . memory . pointer_size ( ) as isize ;
1120
+ let dest_extra = dest. offset ( ptr_size) ;
1121
+ self . memory . write_ptr ( dest_extra, vtable) ?;
1122
+ } ,
1123
+
1124
+ _ => bug ! ( "invalid unsizing {:?} -> {:?}" , src_ty, dest_ty) ,
1125
+ }
1126
+ }
1127
+ ( & ty:: TyAdt ( def_a, substs_a) , & ty:: TyAdt ( def_b, substs_b) ) => {
1128
+ // unsizing of generic struct with pointer fields
1129
+ // Example: `Arc<T>` -> `Arc<Trait>`
1130
+ // here we need to increase the size of every &T thin ptr field to a fat ptr
1131
+
1132
+ assert_eq ! ( def_a, def_b) ;
1133
+
1134
+ let src_fields = def_a. variants [ 0 ] . fields . iter ( ) ;
1135
+ let dst_fields = def_b. variants [ 0 ] . fields . iter ( ) ;
1136
+
1137
+ //let src = adt::MaybeSizedValue::sized(src);
1138
+ //let dst = adt::MaybeSizedValue::sized(dst);
1139
+ let src_ptr = match src {
1140
+ Value :: ByRef ( ptr) => ptr,
1141
+ _ => panic ! ( "expected pointer, got {:?}" , src) ,
1142
+ } ;
1143
+
1144
+ let iter = src_fields. zip ( dst_fields) . enumerate ( ) ;
1145
+ for ( i, ( src_f, dst_f) ) in iter {
1146
+ let src_fty = self . monomorphize_field_ty ( src_f, substs_a) ;
1147
+ let dst_fty = self . monomorphize_field_ty ( dst_f, substs_b) ;
1148
+ if self . type_size ( dst_fty) == 0 {
1149
+ continue ;
1150
+ }
1151
+ let src_field_offset = self . get_field_offset ( src_ty, i) ?. bytes ( ) as isize ;
1152
+ let dst_field_offset = self . get_field_offset ( dest_ty, i) ?. bytes ( ) as isize ;
1153
+ let src_f_ptr = src_ptr. offset ( src_field_offset) ;
1154
+ let dst_f_ptr = dest. offset ( dst_field_offset) ;
1155
+ if src_fty == dst_fty {
1156
+ self . move_ ( src_f_ptr, dst_f_ptr, src_fty) ?;
1157
+ } else {
1158
+ self . unsize_into ( Value :: ByRef ( src_f_ptr) , src_fty, dst_f_ptr, dst_fty) ?;
1159
+ }
1160
+ }
1161
+ }
1162
+ _ => bug ! ( "unsize_into: invalid conversion: {:?} -> {:?}" ,
1163
+ src_ty,
1164
+ dest_ty) ,
1117
1165
}
1118
- _ => None ,
1166
+ Ok ( ( ) )
1119
1167
}
1120
1168
}
1121
1169
0 commit comments