@@ -238,27 +238,46 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
238
238
let ( lvalue, target) = destination. expect ( "tuple struct constructors can't diverge" ) ;
239
239
let dest_ty = self . tcx . item_type ( adt_def. did ) ;
240
240
let dest_layout = self . type_layout ( dest_ty) ?;
241
- let disr = v . disr_val . to_u128_unchecked ( ) ;
241
+ trace ! ( "layout({:?}) = {:#?}" , dest_ty , dest_layout ) ;
242
242
match * dest_layout {
243
243
Layout :: Univariant { ref variant, .. } => {
244
- assert_eq ! ( disr, 0 ) ;
244
+ let disr_val = v. disr_val . to_u128_unchecked ( ) ;
245
+ assert_eq ! ( disr_val, 0 ) ;
245
246
let offsets = variant. offsets . iter ( ) . map ( |s| s. bytes ( ) ) ;
246
247
247
248
self . assign_fields ( lvalue, offsets, args) ?;
248
249
} ,
249
250
Layout :: General { discr, ref variants, .. } => {
250
- // FIXME: report a proper error for invalid discriminants
251
- // right now we simply go into index out of bounds
251
+ let disr_val = v. disr_val . to_u128_unchecked ( ) ;
252
252
let discr_size = discr. size ( ) . bytes ( ) ;
253
253
self . assign_discr_and_fields (
254
254
lvalue,
255
- variants[ disr as usize ] . offsets . iter ( ) . cloned ( ) . map ( Size :: bytes) ,
255
+ variants[ disr_val as usize ] . offsets . iter ( ) . cloned ( ) . map ( Size :: bytes) ,
256
256
args,
257
- disr ,
257
+ disr_val ,
258
258
discr_size,
259
259
) ?;
260
260
} ,
261
- Layout :: StructWrappedNullablePointer { .. } |
261
+ Layout :: StructWrappedNullablePointer { nndiscr, ref nonnull, ref discrfield, .. } => {
262
+ let disr_val = v. disr_val . to_u128_unchecked ( ) ;
263
+ if nndiscr as u128 == disr_val {
264
+ let offsets = nonnull. offsets . iter ( ) . map ( |s| s. bytes ( ) ) ;
265
+ self . assign_fields ( lvalue, offsets, args) ?;
266
+ } else {
267
+ for ( _, ty) in args {
268
+ assert_eq ! ( self . type_size( ty) ?, Some ( 0 ) ) ;
269
+ }
270
+ let ( offset, ty) = self . nonnull_offset_and_ty ( dest_ty, nndiscr, discrfield) ?;
271
+
272
+ // FIXME(solson)
273
+ let dest = self . force_allocation ( lvalue) ?. to_ptr ( ) ;
274
+
275
+ let dest = dest. offset ( offset. bytes ( ) ) ;
276
+ let dest_size = self . type_size ( ty) ?
277
+ . expect ( "bad StructWrappedNullablePointer discrfield" ) ;
278
+ self . memory . write_int ( dest, 0 , dest_size) ?;
279
+ }
280
+ } ,
262
281
Layout :: RawNullablePointer { .. } => {
263
282
assert_eq ! ( args. len( ) , 1 ) ;
264
283
let ( val, ty) = args. pop ( ) . unwrap ( ) ;
@@ -307,7 +326,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
307
326
fn read_discriminant_value ( & self , adt_ptr : Pointer , adt_ty : Ty < ' tcx > ) -> EvalResult < ' tcx , u128 > {
308
327
use rustc:: ty:: layout:: Layout :: * ;
309
328
let adt_layout = self . type_layout ( adt_ty) ?;
310
- trace ! ( "read_discriminant_value {:?}" , adt_layout) ;
329
+ trace ! ( "read_discriminant_value {:# ?}" , adt_layout) ;
311
330
312
331
let discr_val = match * adt_layout {
313
332
General { discr, .. } | CEnum { discr, signed : false , .. } => {
@@ -344,6 +363,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
344
363
}
345
364
346
365
fn read_nonnull_discriminant_value ( & self , ptr : Pointer , nndiscr : u128 , discr_size : u64 ) -> EvalResult < ' tcx , u128 > {
366
+ trace ! ( "read_nonnull_discriminant_value: {:?}, {}, {}" , ptr, nndiscr, discr_size) ;
347
367
let not_null = match self . memory . read_uint ( ptr, discr_size) {
348
368
Ok ( 0 ) => false ,
349
369
Ok ( _) | Err ( EvalError :: ReadPointerAsBytes ) => true ,
0 commit comments