@@ -24,40 +24,43 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
2424 cast_ty : Ty < ' tcx > ,
2525 dest : & PlaceTy < ' tcx , M :: Provenance > ,
2626 ) -> InterpResult < ' tcx > {
27+ // `cast_ty` will often be the same as `dest.ty`, but not always, since subtyping is still
28+ // possible.
29+ let cast_layout =
30+ if cast_ty == dest. layout . ty { dest. layout } else { self . layout_of ( cast_ty) ? } ;
2731 // FIXME: In which cases should we trigger UB when the source is uninit?
2832 match cast_kind {
2933 CastKind :: PointerCoercion ( PointerCoercion :: Unsize ) => {
30- let cast_ty = self . layout_of ( cast_ty) ?;
31- self . unsize_into ( src, cast_ty, dest) ?;
34+ self . unsize_into ( src, cast_layout, dest) ?;
3235 }
3336
3437 CastKind :: PointerExposeAddress => {
3538 let src = self . read_immediate ( src) ?;
36- let res = self . pointer_expose_address_cast ( & src, cast_ty ) ?;
39+ let res = self . pointer_expose_address_cast ( & src, cast_layout ) ?;
3740 self . write_immediate ( * res, dest) ?;
3841 }
3942
4043 CastKind :: PointerFromExposedAddress => {
4144 let src = self . read_immediate ( src) ?;
42- let res = self . pointer_from_exposed_address_cast ( & src, cast_ty ) ?;
45+ let res = self . pointer_from_exposed_address_cast ( & src, cast_layout ) ?;
4346 self . write_immediate ( * res, dest) ?;
4447 }
4548
4649 CastKind :: IntToInt | CastKind :: IntToFloat => {
4750 let src = self . read_immediate ( src) ?;
48- let res = self . int_to_int_or_float ( & src, cast_ty ) ?;
51+ let res = self . int_to_int_or_float ( & src, cast_layout ) ?;
4952 self . write_immediate ( * res, dest) ?;
5053 }
5154
5255 CastKind :: FloatToFloat | CastKind :: FloatToInt => {
5356 let src = self . read_immediate ( src) ?;
54- let res = self . float_to_float_or_int ( & src, cast_ty ) ?;
57+ let res = self . float_to_float_or_int ( & src, cast_layout ) ?;
5558 self . write_immediate ( * res, dest) ?;
5659 }
5760
5861 CastKind :: FnPtrToPtr | CastKind :: PtrToPtr => {
5962 let src = self . read_immediate ( src) ?;
60- let res = self . ptr_to_ptr ( & src, cast_ty ) ?;
63+ let res = self . ptr_to_ptr ( & src, cast_layout ) ?;
6164 self . write_immediate ( * res, dest) ?;
6265 }
6366
@@ -140,6 +143,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
140143 CastKind :: Transmute => {
141144 assert ! ( src. layout. is_sized( ) ) ;
142145 assert ! ( dest. layout. is_sized( ) ) ;
146+ assert_eq ! ( cast_ty, dest. layout. ty) ; // we otherwise ignore `cast_ty` enirely...
143147 if src. layout . size != dest. layout . size {
144148 let src_bytes = src. layout . size . bytes ( ) ;
145149 let dest_bytes = dest. layout . size . bytes ( ) ;
@@ -164,64 +168,61 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
164168 pub fn int_to_int_or_float (
165169 & self ,
166170 src : & ImmTy < ' tcx , M :: Provenance > ,
167- cast_ty : Ty < ' tcx > ,
171+ cast_to : TyAndLayout < ' tcx > ,
168172 ) -> InterpResult < ' tcx , ImmTy < ' tcx , M :: Provenance > > {
169173 assert ! ( src. layout. ty. is_integral( ) || src. layout. ty. is_char( ) || src. layout. ty. is_bool( ) ) ;
170- assert ! ( cast_ty . is_floating_point( ) || cast_ty . is_integral( ) || cast_ty . is_char( ) ) ;
174+ assert ! ( cast_to . ty . is_floating_point( ) || cast_to . ty . is_integral( ) || cast_to . ty . is_char( ) ) ;
171175
172- let layout = self . layout_of ( cast_ty) ?;
173176 Ok ( ImmTy :: from_scalar (
174- self . cast_from_int_like ( src. to_scalar ( ) , src. layout , cast_ty ) ?,
175- layout ,
177+ self . cast_from_int_like ( src. to_scalar ( ) , src. layout , cast_to . ty ) ?,
178+ cast_to ,
176179 ) )
177180 }
178181
179182 /// Handles 'FloatToFloat' and 'FloatToInt' casts.
180183 pub fn float_to_float_or_int (
181184 & self ,
182185 src : & ImmTy < ' tcx , M :: Provenance > ,
183- cast_ty : Ty < ' tcx > ,
186+ cast_to : TyAndLayout < ' tcx > ,
184187 ) -> InterpResult < ' tcx , ImmTy < ' tcx , M :: Provenance > > {
185188 use rustc_type_ir:: sty:: TyKind :: * ;
186189
187- let layout = self . layout_of ( cast_ty) ?;
188190 let val = match src. layout . ty . kind ( ) {
189191 // Floating point
190- Float ( FloatTy :: F32 ) => self . cast_from_float ( src. to_scalar ( ) . to_f32 ( ) ?, cast_ty ) ,
191- Float ( FloatTy :: F64 ) => self . cast_from_float ( src. to_scalar ( ) . to_f64 ( ) ?, cast_ty ) ,
192+ Float ( FloatTy :: F32 ) => self . cast_from_float ( src. to_scalar ( ) . to_f32 ( ) ?, cast_to . ty ) ,
193+ Float ( FloatTy :: F64 ) => self . cast_from_float ( src. to_scalar ( ) . to_f64 ( ) ?, cast_to . ty ) ,
192194 _ => {
193- bug ! ( "Can't cast 'Float' type into {}" , cast_ty ) ;
195+ bug ! ( "Can't cast 'Float' type into {}" , cast_to . ty ) ;
194196 }
195197 } ;
196- Ok ( ImmTy :: from_scalar ( val, layout ) )
198+ Ok ( ImmTy :: from_scalar ( val, cast_to ) )
197199 }
198200
199201 /// Handles 'FnPtrToPtr' and 'PtrToPtr' casts.
200202 pub fn ptr_to_ptr (
201203 & self ,
202204 src : & ImmTy < ' tcx , M :: Provenance > ,
203- cast_ty : Ty < ' tcx > ,
205+ cast_to : TyAndLayout < ' tcx > ,
204206 ) -> InterpResult < ' tcx , ImmTy < ' tcx , M :: Provenance > > {
205207 assert ! ( src. layout. ty. is_any_ptr( ) ) ;
206- assert ! ( cast_ty . is_unsafe_ptr( ) ) ;
208+ assert ! ( cast_to . ty . is_unsafe_ptr( ) ) ;
207209 // Handle casting any ptr to raw ptr (might be a fat ptr).
208- let dest_layout = self . layout_of ( cast_ty) ?;
209- if dest_layout. size == src. layout . size {
210+ if cast_to. size == src. layout . size {
210211 // Thin or fat pointer that just hast the ptr kind of target type changed.
211- return Ok ( ImmTy :: from_immediate ( * * src, dest_layout ) ) ;
212+ return Ok ( ImmTy :: from_immediate ( * * src, cast_to ) ) ;
212213 } else {
213214 // Casting the metadata away from a fat ptr.
214215 assert_eq ! ( src. layout. size, 2 * self . pointer_size( ) ) ;
215- assert_eq ! ( dest_layout . size, self . pointer_size( ) ) ;
216+ assert_eq ! ( cast_to . size, self . pointer_size( ) ) ;
216217 assert ! ( src. layout. ty. is_unsafe_ptr( ) ) ;
217218 return match * * src {
218- Immediate :: ScalarPair ( data, _) => Ok ( ImmTy :: from_scalar ( data, dest_layout ) ) ,
219+ Immediate :: ScalarPair ( data, _) => Ok ( ImmTy :: from_scalar ( data, cast_to ) ) ,
219220 Immediate :: Scalar ( ..) => span_bug ! (
220221 self . cur_span( ) ,
221222 "{:?} input to a fat-to-thin cast ({} -> {})" ,
222223 * src,
223224 src. layout. ty,
224- cast_ty
225+ cast_to . ty
225226 ) ,
226227 Immediate :: Uninit => throw_ub ! ( InvalidUninitBytes ( None ) ) ,
227228 } ;
@@ -231,28 +232,27 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
231232 pub fn pointer_expose_address_cast (
232233 & mut self ,
233234 src : & ImmTy < ' tcx , M :: Provenance > ,
234- cast_ty : Ty < ' tcx > ,
235+ cast_to : TyAndLayout < ' tcx > ,
235236 ) -> InterpResult < ' tcx , ImmTy < ' tcx , M :: Provenance > > {
236237 assert_matches ! ( src. layout. ty. kind( ) , ty:: RawPtr ( _) | ty:: FnPtr ( _) ) ;
237- assert ! ( cast_ty . is_integral( ) ) ;
238+ assert ! ( cast_to . ty . is_integral( ) ) ;
238239
239240 let scalar = src. to_scalar ( ) ;
240241 let ptr = scalar. to_pointer ( self ) ?;
241242 match ptr. into_pointer_or_addr ( ) {
242243 Ok ( ptr) => M :: expose_ptr ( self , ptr) ?,
243244 Err ( _) => { } // Do nothing, exposing an invalid pointer (`None` provenance) is a NOP.
244245 } ;
245- let layout = self . layout_of ( cast_ty) ?;
246- Ok ( ImmTy :: from_scalar ( self . cast_from_int_like ( scalar, src. layout , cast_ty) ?, layout) )
246+ Ok ( ImmTy :: from_scalar ( self . cast_from_int_like ( scalar, src. layout , cast_to. ty ) ?, cast_to) )
247247 }
248248
249249 pub fn pointer_from_exposed_address_cast (
250250 & self ,
251251 src : & ImmTy < ' tcx , M :: Provenance > ,
252- cast_ty : Ty < ' tcx > ,
252+ cast_to : TyAndLayout < ' tcx > ,
253253 ) -> InterpResult < ' tcx , ImmTy < ' tcx , M :: Provenance > > {
254254 assert ! ( src. layout. ty. is_integral( ) ) ;
255- assert_matches ! ( cast_ty . kind( ) , ty:: RawPtr ( _) ) ;
255+ assert_matches ! ( cast_to . ty . kind( ) , ty:: RawPtr ( _) ) ;
256256
257257 // First cast to usize.
258258 let scalar = src. to_scalar ( ) ;
@@ -261,8 +261,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
261261
262262 // Then turn address into pointer.
263263 let ptr = M :: ptr_from_addr_cast ( & self , addr) ?;
264- let layout = self . layout_of ( cast_ty) ?;
265- Ok ( ImmTy :: from_scalar ( Scalar :: from_maybe_pointer ( ptr, self ) , layout) )
264+ Ok ( ImmTy :: from_scalar ( Scalar :: from_maybe_pointer ( ptr, self ) , cast_to) )
266265 }
267266
268267 /// Low-level cast helper function. This works directly on scalars and can take 'int-like' input
0 commit comments