@@ -7,7 +7,7 @@ use syntax::symbol::sym;
77use rustc_apfloat:: ieee:: { Single , Double } ;
88use rustc_apfloat:: { Float , FloatConvert } ;
99use rustc:: mir:: interpret:: {
10- Scalar , InterpResult , Pointer , PointerArithmetic , InterpError ,
10+ Scalar , InterpResult , PointerArithmetic , InterpError ,
1111} ;
1212use rustc:: mir:: CastKind ;
1313
@@ -111,15 +111,29 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
111111 )
112112 }
113113
114+ // Handle cast from a univariant (ZST) enum
115+ match src. layout . variants {
116+ layout:: Variants :: Single { index } => {
117+ if let Some ( discr) =
118+ src. layout . ty . discriminant_for_variant ( * self . tcx , index)
119+ {
120+ assert ! ( src. layout. is_zst( ) ) ;
121+ return Ok ( Scalar :: from_uint ( discr. val , dest_layout. size ) . into ( ) ) ;
122+ }
123+ }
124+ layout:: Variants :: Multiple { .. } => { } ,
125+ }
126+
114127 // Handle casting the metadata away from a fat pointer.
115128 if src. layout . ty . is_unsafe_ptr ( ) && dest_layout. ty . is_unsafe_ptr ( ) &&
116129 dest_layout. size != src. layout . size
117130 {
118131 assert_eq ! ( src. layout. size, 2 * self . memory. pointer_size( ) ) ;
119132 assert_eq ! ( dest_layout. size, self . memory. pointer_size( ) ) ;
120133 assert ! ( dest_layout. ty. is_unsafe_ptr( ) ) ;
121- return match * src {
122- Immediate :: ScalarPair ( data, _) => Ok ( data. into ( ) ) ,
134+ match * src {
135+ Immediate :: ScalarPair ( data, _) =>
136+ return Ok ( data. into ( ) ) ,
123137 Immediate :: Scalar ( ..) =>
124138 bug ! (
125139 "{:?} input to a fat-to-thin cast ({:?} -> {:?})" ,
@@ -128,34 +142,21 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
128142 } ;
129143 }
130144
131- // Handle casting reference to raw ptr or raw to other raw (might be a fat ptr).
132- if ( src. layout . ty . is_region_ptr ( ) || src. layout . ty . is_unsafe_ptr ( ) ) &&
145+ // Handle casting any ptr to raw ptr (might be a fat ptr).
146+ if ( src. layout . ty . is_region_ptr ( ) || src. layout . ty . is_unsafe_ptr ( ) || src . layout . ty . is_fn_ptr ( ) ) &&
133147 dest_layout. ty . is_unsafe_ptr ( )
134148 {
135149 // The only possible size-unequal case was handled above.
136150 assert_eq ! ( src. layout. size, dest_layout. size) ;
137151 return Ok ( * src) ;
138152 }
139153
140- // Handle cast from a univariant (ZST) enum
141- match src. layout . variants {
142- layout:: Variants :: Single { index } => {
143- if let Some ( discr) =
144- src. layout . ty . discriminant_for_variant ( * self . tcx , index)
145- {
146- assert ! ( src. layout. is_zst( ) ) ;
147- return Ok ( Scalar :: from_uint ( discr. val , dest_layout. size ) . into ( ) ) ;
148- }
149- }
150- layout:: Variants :: Multiple { .. } => { } ,
151- }
152-
153- // Handle all the rest.
154- let val = src. to_scalar ( ) ?;
155- Ok ( match val. to_bits_or_ptr ( src. layout . size , self ) {
156- Err ( ptr) => self . cast_from_ptr ( ptr, src. layout , dest_layout) ?,
157- Ok ( data) => self . cast_from_int ( data, src. layout , dest_layout) ?,
158- } . into ( ) )
154+ // For all remaining casts, we either
155+ // (a) cast a raw ptr to usize, or
156+ // (b) cast from an integer-like (including bool, char, enums).
157+ // In both cases we want the bits.
158+ let bits = self . force_bits ( src. to_scalar ( ) ?, src. layout . size ) ?;
159+ Ok ( self . cast_from_int ( bits, src. layout , dest_layout) ?. into ( ) )
159160 }
160161
161162 fn cast_from_int (
@@ -236,27 +237,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
236237 }
237238 }
238239
239- fn cast_from_ptr (
240- & self ,
241- ptr : Pointer < M :: PointerTag > ,
242- src_layout : TyLayout < ' tcx > ,
243- dest_layout : TyLayout < ' tcx > ,
244- ) -> InterpResult < ' tcx , Scalar < M :: PointerTag > > {
245- use rustc:: ty:: TyKind :: * ;
246-
247- match dest_layout. ty . sty {
248- // Casting to a reference or fn pointer is not permitted by rustc,
249- // no need to support it here.
250- RawPtr ( _) => Ok ( ptr. into ( ) ) ,
251- Int ( _) | Uint ( _) => {
252- let size = self . memory . pointer_size ( ) ;
253- let bits = self . force_bits ( Scalar :: Ptr ( ptr) , size) ?;
254- self . cast_from_int ( bits, src_layout, dest_layout)
255- }
256- _ => bug ! ( "invalid MIR: ptr to {:?} cast" , dest_layout. ty)
257- }
258- }
259-
260240 fn unsize_into_ptr (
261241 & mut self ,
262242 src : OpTy < ' tcx , M :: PointerTag > ,
0 commit comments