@@ -14,15 +14,6 @@ use rustc::mir::CastKind;
1414use super :: { InterpCx , Machine , PlaceTy , OpTy , ImmTy , Immediate , FnVal } ;
1515
1616impl < ' mir , ' tcx , M : Machine < ' mir , ' tcx > > InterpCx < ' mir , ' tcx , M > {
17- fn type_is_fat_ptr ( & self , ty : Ty < ' tcx > ) -> bool {
18- match ty. sty {
19- ty:: RawPtr ( ty:: TypeAndMut { ty, .. } ) |
20- ty:: Ref ( _, ty, _) => !self . type_is_sized ( ty) ,
21- ty:: Adt ( def, _) if def. is_box ( ) => !self . type_is_sized ( ty. boxed_ty ( ) ) ,
22- _ => false ,
23- }
24- }
25-
2617 pub fn cast (
2718 & mut self ,
2819 src : OpTy < ' tcx , M :: PointerTag > ,
@@ -99,68 +90,59 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
9990 src : ImmTy < ' tcx , M :: PointerTag > ,
10091 dest_layout : TyLayout < ' tcx > ,
10192 ) -> InterpResult < ' tcx , Immediate < M :: PointerTag > > {
102- if self . type_is_fat_ptr ( src. layout . ty ) {
103- return match ( * src, self . type_is_fat_ptr ( dest_layout. ty ) ) {
104- // pointers to extern types
105- ( Immediate :: Scalar ( _) , _) |
106- // slices and trait objects to other slices/trait objects
107- ( Immediate :: ScalarPair ( ..) , true ) => {
108- // No change to immediate
109- Ok ( * src)
110- }
111- // slices and trait objects to thin pointers (dropping the metadata)
112- ( Immediate :: ScalarPair ( data, _) , false ) => {
113- Ok ( data. into ( ) )
114- }
115- } ;
116- } else {
117- match src. layout . variants {
118- layout:: Variants :: Single { index } => {
119- if let Some ( discr) =
120- src. layout . ty . discriminant_for_variant ( * self . tcx , index)
121- {
122- // Cast from a univariant enum
123- assert ! ( src. layout. is_zst( ) ) ;
124- return Ok ( Scalar :: from_uint ( discr. val , dest_layout. size ) . into ( ) ) ;
125- }
126- }
127- layout:: Variants :: Multiple { .. } => { } ,
128- }
129-
130- return Ok ( self . cast_scalar ( src. to_scalar ( ) ?, src. layout , dest_layout) ?. into ( ) ) ;
131- }
132- }
133-
134- fn cast_scalar (
135- & self ,
136- val : Scalar < M :: PointerTag > ,
137- src_layout : TyLayout < ' tcx > ,
138- dest_layout : TyLayout < ' tcx > ,
139- ) -> InterpResult < ' tcx , Scalar < M :: PointerTag > > {
14093 use rustc:: ty:: TyKind :: * ;
141- trace ! ( "Casting {:?}: {:?} to {:?}" , val , src_layout . ty, dest_layout. ty) ;
94+ trace ! ( "Casting {:?}: {:?} to {:?}" , * src , src . layout . ty, dest_layout. ty) ;
14295
143- match src_layout . ty . sty {
96+ match src . layout . ty . sty {
14497 // Floating point
145- Float ( FloatTy :: F32 ) => self . cast_from_float ( val. to_f32 ( ) ?, dest_layout. ty ) ,
146- Float ( FloatTy :: F64 ) => self . cast_from_float ( val. to_f64 ( ) ?, dest_layout. ty ) ,
147- // Integer(-like), including fn ptr casts and casts from enums that
148- // are represented as integers (this excludes univariant enums, which
149- // are handled in `cast` directly).
150- _ => {
98+ Float ( FloatTy :: F32 ) =>
99+ return Ok ( self . cast_from_float ( src. to_scalar ( ) ?. to_f32 ( ) ?, dest_layout. ty ) ?. into ( ) ) ,
100+ Float ( FloatTy :: F64 ) =>
101+ return Ok ( self . cast_from_float ( src. to_scalar ( ) ?. to_f64 ( ) ?, dest_layout. ty ) ?. into ( ) ) ,
102+ // The rest is integer/pointer-"like", including fn ptr casts and casts from enums that
103+ // are represented as integers.
104+ _ =>
151105 assert ! (
152- src_layout. ty. is_bool( ) || src_layout. ty. is_char( ) ||
153- src_layout. ty. is_enum( ) || src_layout. ty. is_integral( ) ||
154- src_layout. ty. is_unsafe_ptr( ) || src_layout. ty. is_fn_ptr( ) ||
155- src_layout. ty. is_region_ptr( ) ,
156- "Unexpected cast from type {:?}" , src_layout. ty
157- ) ;
158- match val. to_bits_or_ptr ( src_layout. size , self ) {
159- Err ( ptr) => self . cast_from_ptr ( ptr, src_layout, dest_layout) ,
160- Ok ( data) => self . cast_from_int ( data, src_layout, dest_layout) ,
106+ src. layout. ty. is_bool( ) || src. layout. ty. is_char( ) ||
107+ src. layout. ty. is_enum( ) || src. layout. ty. is_integral( ) ||
108+ src. layout. ty. is_unsafe_ptr( ) || src. layout. ty. is_fn_ptr( ) ||
109+ src. layout. ty. is_region_ptr( ) ,
110+ "Unexpected cast from type {:?}" , src. layout. ty
111+ )
112+ }
113+
114+ // Handle cast the metadata away from a fat pointer.
115+ if dest_layout. size != src. layout . size {
116+ assert_eq ! ( dest_layout. size, self . memory. pointer_size( ) ) ;
117+ return match * src {
118+ Immediate :: ScalarPair ( data, _) => Ok ( data. into ( ) ) ,
119+ Immediate :: Scalar ( ..) =>
120+ bug ! (
121+ "{:?} input to a fat-to-thin cast ({:?} -> {:?})" ,
122+ * src, src. layout. ty, dest_layout. ty
123+ ) ,
124+ } ;
125+ }
126+
127+ // Handle cast from a univariant (ZST) enum
128+ match src. layout . variants {
129+ layout:: Variants :: Single { index } => {
130+ if let Some ( discr) =
131+ src. layout . ty . discriminant_for_variant ( * self . tcx , index)
132+ {
133+ assert ! ( src. layout. is_zst( ) ) ;
134+ return Ok ( Scalar :: from_uint ( discr. val , dest_layout. size ) . into ( ) ) ;
161135 }
162136 }
137+ layout:: Variants :: Multiple { .. } => { } ,
163138 }
139+
140+ // Handle all the rest.
141+ let val = src. to_scalar ( ) ?;
142+ Ok ( match val. to_bits_or_ptr ( src. layout . size , self ) {
143+ Err ( ptr) => self . cast_from_ptr ( ptr, src. layout , dest_layout) ?,
144+ Ok ( data) => self . cast_from_int ( data, src. layout , dest_layout) ?,
145+ } . into ( ) )
164146 }
165147
166148 fn cast_from_int (
0 commit comments