@@ -98,7 +98,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
9898 }
9999
100100 pub fn misc_cast (
101- & self ,
101+ & mut self ,
102102 src : & ImmTy < ' tcx , M :: PointerTag > ,
103103 cast_ty : Ty < ' tcx > ,
104104 ) -> InterpResult < ' tcx , Immediate < M :: PointerTag > > {
@@ -139,7 +139,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
139139 if let Some ( discr) = src. layout . ty . discriminant_for_variant ( * self . tcx , index) {
140140 assert ! ( src. layout. is_zst( ) ) ;
141141 let discr_layout = self . layout_of ( discr. ty ) ?;
142- return Ok ( self . cast_from_int_like ( discr. val , discr_layout, cast_ty) . into ( ) ) ;
142+
143+ let scalar = Scalar :: from_uint ( discr. val , discr_layout. layout . size ( ) ) ;
144+ return Ok ( self . cast_from_int_like ( scalar, discr_layout, cast_ty) ?. into ( ) ) ;
143145 }
144146 }
145147 Variants :: Multiple { .. } => { }
@@ -170,38 +172,65 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
170172 }
171173
172174 // # The remaining source values are scalar and "int-like".
175+ let scalar = src. to_scalar ( ) ?;
176+
177+ // If we are casting from a pointer to something
178+ // that is not a pointer, mark the pointer as exposed
179+ if src. layout . ty . is_any_ptr ( ) && !cast_ty. is_any_ptr ( ) {
180+ let ptr = self . scalar_to_ptr ( scalar) ?;
181+
182+ match ptr. into_pointer_or_addr ( ) {
183+ Ok ( ptr) => {
184+ M :: expose_ptr ( self , ptr) ?;
185+ }
186+ Err ( _) => {
187+ // do nothing, exposing an invalid pointer
188+ // has no meaning
189+ }
190+ } ;
191+ }
173192
174- // For all remaining casts, we either
175- // (a) cast a raw ptr to usize, or
176- // (b) cast from an integer-like (including bool, char, enums).
177- // In both cases we want the bits.
178- let bits = src. to_scalar ( ) ?. to_bits ( src. layout . size ) ?;
179- Ok ( self . cast_from_int_like ( bits, src. layout , cast_ty) . into ( ) )
193+ Ok ( self . cast_from_int_like ( scalar, src. layout , cast_ty) ?. into ( ) )
180194 }
181195
182- fn cast_from_int_like (
196+ pub fn cast_from_int_like (
183197 & self ,
184- v : u128 , // raw bits (there is no ScalarTy so we separate data+layout)
198+ scalar : Scalar < M :: PointerTag > , // input value (there is no ScalarTy so we separate data+layout)
185199 src_layout : TyAndLayout < ' tcx > ,
186200 cast_ty : Ty < ' tcx > ,
187- ) -> Scalar < M :: PointerTag > {
201+ ) -> InterpResult < ' tcx , Scalar < M :: PointerTag > > {
188202 // Let's make sure v is sign-extended *if* it has a signed type.
189203 let signed = src_layout. abi . is_signed ( ) ; // Also asserts that abi is `Scalar`.
204+
205+ let v = scalar. to_bits ( src_layout. size ) ?;
190206 let v = if signed { self . sign_extend ( v, src_layout) } else { v } ;
191207 trace ! ( "cast_from_scalar: {}, {} -> {}" , v, src_layout. ty, cast_ty) ;
192208 use rustc_middle:: ty:: TyKind :: * ;
193- match * cast_ty. kind ( ) {
194- Int ( _) | Uint ( _) | RawPtr ( _) => {
209+
210+ Ok ( match * cast_ty. kind ( ) {
211+ Int ( _) | Uint ( _) => {
195212 let size = match * cast_ty. kind ( ) {
196213 Int ( t) => Integer :: from_int_ty ( self , t) . size ( ) ,
197214 Uint ( t) => Integer :: from_uint_ty ( self , t) . size ( ) ,
198- RawPtr ( _) => self . pointer_size ( ) ,
199215 _ => bug ! ( ) ,
200216 } ;
201217 let v = size. truncate ( v) ;
202218 Scalar :: from_uint ( v, size)
203219 }
204220
221+ RawPtr ( _) => {
222+ assert ! ( src_layout. ty. is_integral( ) ) ;
223+
224+ let size = self . pointer_size ( ) ;
225+ let addr = u64:: try_from ( size. truncate ( v) ) . unwrap ( ) ;
226+
227+ let ptr = M :: ptr_from_addr_cast ( & self , addr) ;
228+ if addr == 0 {
229+ assert ! ( ptr. provenance. is_none( ) , "null pointer can never have an AllocId" ) ;
230+ }
231+ Scalar :: from_maybe_pointer ( ptr, self )
232+ }
233+
205234 Float ( FloatTy :: F32 ) if signed => Scalar :: from_f32 ( Single :: from_i128 ( v as i128 ) . value ) ,
206235 Float ( FloatTy :: F64 ) if signed => Scalar :: from_f64 ( Double :: from_i128 ( v as i128 ) . value ) ,
207236 Float ( FloatTy :: F32 ) => Scalar :: from_f32 ( Single :: from_u128 ( v) . value ) ,
@@ -214,7 +243,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
214243
215244 // Casts to bool are not permitted by rustc, no need to handle them here.
216245 _ => span_bug ! ( self . cur_span( ) , "invalid int to {:?} cast" , cast_ty) ,
217- }
246+ } )
218247 }
219248
220249 fn cast_from_float < F > ( & self , f : F , dest_ty : Ty < ' tcx > ) -> Scalar < M :: PointerTag >
0 commit comments