@@ -7,7 +7,7 @@ use syntax::symbol::sym;
7
7
use rustc_apfloat:: ieee:: { Single , Double } ;
8
8
use rustc_apfloat:: { Float , FloatConvert } ;
9
9
use rustc:: mir:: interpret:: {
10
- Scalar , InterpResult , Pointer , PointerArithmetic , InterpError ,
10
+ Scalar , InterpResult , PointerArithmetic , InterpError ,
11
11
} ;
12
12
use rustc:: mir:: CastKind ;
13
13
@@ -111,15 +111,29 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
111
111
)
112
112
}
113
113
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
+
114
127
// Handle casting the metadata away from a fat pointer.
115
128
if src. layout . ty . is_unsafe_ptr ( ) && dest_layout. ty . is_unsafe_ptr ( ) &&
116
129
dest_layout. size != src. layout . size
117
130
{
118
131
assert_eq ! ( src. layout. size, 2 * self . memory. pointer_size( ) ) ;
119
132
assert_eq ! ( dest_layout. size, self . memory. pointer_size( ) ) ;
120
133
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 ( ) ) ,
123
137
Immediate :: Scalar ( ..) =>
124
138
bug ! (
125
139
"{:?} input to a fat-to-thin cast ({:?} -> {:?})" ,
@@ -128,34 +142,21 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
128
142
} ;
129
143
}
130
144
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 ( ) ) &&
133
147
dest_layout. ty . is_unsafe_ptr ( )
134
148
{
135
149
// The only possible size-unequal case was handled above.
136
150
assert_eq ! ( src. layout. size, dest_layout. size) ;
137
151
return Ok ( * src) ;
138
152
}
139
153
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 ( ) )
159
160
}
160
161
161
162
fn cast_from_int (
@@ -236,27 +237,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
236
237
}
237
238
}
238
239
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
-
260
240
fn unsize_into_ptr (
261
241
& mut self ,
262
242
src : OpTy < ' tcx , M :: PointerTag > ,
0 commit comments