@@ -98,7 +98,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
98
98
}
99
99
100
100
pub fn misc_cast (
101
- & self ,
101
+ & mut self ,
102
102
src : & ImmTy < ' tcx , M :: PointerTag > ,
103
103
cast_ty : Ty < ' tcx > ,
104
104
) -> InterpResult < ' tcx , Immediate < M :: PointerTag > > {
@@ -139,7 +139,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
139
139
if let Some ( discr) = src. layout . ty . discriminant_for_variant ( * self . tcx , index) {
140
140
assert ! ( src. layout. is_zst( ) ) ;
141
141
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 ( ) ) ;
143
145
}
144
146
}
145
147
Variants :: Multiple { .. } => { }
@@ -170,38 +172,65 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
170
172
}
171
173
172
174
// # 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
+ }
173
192
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 ( ) )
180
194
}
181
195
182
- fn cast_from_int_like (
196
+ pub fn cast_from_int_like (
183
197
& 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)
185
199
src_layout : TyAndLayout < ' tcx > ,
186
200
cast_ty : Ty < ' tcx > ,
187
- ) -> Scalar < M :: PointerTag > {
201
+ ) -> InterpResult < ' tcx , Scalar < M :: PointerTag > > {
188
202
// Let's make sure v is sign-extended *if* it has a signed type.
189
203
let signed = src_layout. abi . is_signed ( ) ; // Also asserts that abi is `Scalar`.
204
+
205
+ let v = scalar. to_bits ( src_layout. size ) ?;
190
206
let v = if signed { self . sign_extend ( v, src_layout) } else { v } ;
191
207
trace ! ( "cast_from_scalar: {}, {} -> {}" , v, src_layout. ty, cast_ty) ;
192
208
use rustc_middle:: ty:: TyKind :: * ;
193
- match * cast_ty. kind ( ) {
194
- Int ( _) | Uint ( _) | RawPtr ( _) => {
209
+
210
+ Ok ( match * cast_ty. kind ( ) {
211
+ Int ( _) | Uint ( _) => {
195
212
let size = match * cast_ty. kind ( ) {
196
213
Int ( t) => Integer :: from_int_ty ( self , t) . size ( ) ,
197
214
Uint ( t) => Integer :: from_uint_ty ( self , t) . size ( ) ,
198
- RawPtr ( _) => self . pointer_size ( ) ,
199
215
_ => bug ! ( ) ,
200
216
} ;
201
217
let v = size. truncate ( v) ;
202
218
Scalar :: from_uint ( v, size)
203
219
}
204
220
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
+
205
234
Float ( FloatTy :: F32 ) if signed => Scalar :: from_f32 ( Single :: from_i128 ( v as i128 ) . value ) ,
206
235
Float ( FloatTy :: F64 ) if signed => Scalar :: from_f64 ( Double :: from_i128 ( v as i128 ) . value ) ,
207
236
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> {
214
243
215
244
// Casts to bool are not permitted by rustc, no need to handle them here.
216
245
_ => span_bug ! ( self . cur_span( ) , "invalid int to {:?} cast" , cast_ty) ,
217
- }
246
+ } )
218
247
}
219
248
220
249
fn cast_from_float < F > ( & self , f : F , dest_ty : Ty < ' tcx > ) -> Scalar < M :: PointerTag >
0 commit comments