@@ -67,11 +67,12 @@ pub enum PathElem {
67
67
Field ( Symbol ) ,
68
68
Variant ( Symbol ) ,
69
69
GeneratorState ( VariantIdx ) ,
70
- ClosureVar ( Symbol ) ,
70
+ CapturedVar ( Symbol ) ,
71
71
ArrayElem ( usize ) ,
72
72
TupleElem ( usize ) ,
73
73
Deref ,
74
- Tag ,
74
+ EnumTag ,
75
+ GeneratorTag ,
75
76
DynDowncast ,
76
77
}
77
78
@@ -109,17 +110,18 @@ fn write_path(out: &mut String, path: &Vec<PathElem>) {
109
110
for elem in path. iter ( ) {
110
111
match elem {
111
112
Field ( name) => write ! ( out, ".{}" , name) ,
112
- Variant ( name) => write ! ( out, ".<downcast-variant({})>" , name) ,
113
+ EnumTag => write ! ( out, ".<enum-tag>" ) ,
114
+ Variant ( name) => write ! ( out, ".<enum-variant({})>" , name) ,
115
+ GeneratorTag => write ! ( out, ".<generator-tag>" ) ,
113
116
GeneratorState ( idx) => write ! ( out, ".<generator-state({})>" , idx. index( ) ) ,
114
- ClosureVar ( name) => write ! ( out, ".<closure -var({})>" , name) ,
117
+ CapturedVar ( name) => write ! ( out, ".<captured -var({})>" , name) ,
115
118
TupleElem ( idx) => write ! ( out, ".{}" , idx) ,
116
119
ArrayElem ( idx) => write ! ( out, "[{}]" , idx) ,
117
120
// `.<deref>` does not match Rust syntax, but it is more readable for long paths -- and
118
121
// some of the other items here also are not Rust syntax. Actually we can't
119
122
// even use the usual syntax because we are just showing the projections,
120
123
// not the root.
121
124
Deref => write ! ( out, ".<deref>" ) ,
122
- Tag => write ! ( out, ".<enum-tag>" ) ,
123
125
DynDowncast => write ! ( out, ".<dyn-downcast>" ) ,
124
126
}
125
127
. unwrap ( )
@@ -170,6 +172,21 @@ struct ValidityVisitor<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> {
170
172
171
173
impl < ' rt , ' mir , ' tcx , M : Machine < ' mir , ' tcx > > ValidityVisitor < ' rt , ' mir , ' tcx , M > {
172
174
fn aggregate_field_path_elem ( & mut self , layout : TyLayout < ' tcx > , field : usize ) -> PathElem {
175
+ // First, check if we are projecting to a variant.
176
+ match layout. variants {
177
+ layout:: Variants :: Multiple { discr_index, .. } => {
178
+ if discr_index == field {
179
+ return match layout. ty . kind {
180
+ ty:: Adt ( def, ..) if def. is_enum ( ) => PathElem :: EnumTag ,
181
+ ty:: Generator ( ..) => PathElem :: GeneratorTag ,
182
+ _ => bug ! ( "non-variant type {:?}" , layout. ty) ,
183
+ } ;
184
+ }
185
+ }
186
+ layout:: Variants :: Single { .. } => { }
187
+ }
188
+
189
+ // Now we know we are projecting to a field, so figure out which one.
173
190
match layout. ty . kind {
174
191
// generators and closures.
175
192
ty:: Closure ( def_id, _) | ty:: Generator ( def_id, _, _) => {
@@ -190,7 +207,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M
190
207
}
191
208
}
192
209
193
- PathElem :: ClosureVar ( name. unwrap_or_else ( || {
210
+ PathElem :: CapturedVar ( name. unwrap_or_else ( || {
194
211
// Fall back to showing the field index.
195
212
sym:: integer ( field)
196
213
} ) )
@@ -207,10 +224,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M
207
224
// Inside a variant
208
225
PathElem :: Field ( def. variants [ index] . fields [ field] . ident . name )
209
226
}
210
- layout:: Variants :: Multiple { discr_index, .. } => {
211
- assert_eq ! ( discr_index, field) ;
212
- PathElem :: Tag
213
- }
227
+ layout:: Variants :: Multiple { .. } => bug ! ( "we handled variants above" ) ,
214
228
}
215
229
}
216
230
@@ -441,11 +455,12 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M
441
455
fn visit_scalar (
442
456
& mut self ,
443
457
op : OpTy < ' tcx , M :: PointerTag > ,
444
- layout : & layout:: Scalar ,
458
+ scalar_layout : & layout:: Scalar ,
445
459
) -> InterpResult < ' tcx > {
446
460
let value = self . ecx . read_scalar ( op) ?;
461
+ let valid_range = & scalar_layout. valid_range ;
462
+ let ( lo, hi) = valid_range. clone ( ) . into_inner ( ) ;
447
463
// Determine the allowed range
448
- let ( lo, hi) = layout. valid_range . clone ( ) . into_inner ( ) ;
449
464
// `max_hi` is as big as the size fits
450
465
let max_hi = u128:: max_value ( ) >> ( 128 - op. layout . size . bits ( ) ) ;
451
466
assert ! ( hi <= max_hi) ;
@@ -459,7 +474,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M
459
474
value. not_undef( ) ,
460
475
value,
461
476
self . path,
462
- format_args!( "something {}" , wrapping_range_format( & layout . valid_range, max_hi) , )
477
+ format_args!( "something {}" , wrapping_range_format( valid_range, max_hi) , )
463
478
) ;
464
479
let bits = match value. to_bits_or_ptr ( op. layout . size , self . ecx ) {
465
480
Err ( ptr) => {
@@ -471,7 +486,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M
471
486
self . path,
472
487
format_args!(
473
488
"something that cannot possibly fail to be {}" ,
474
- wrapping_range_format( & layout . valid_range, max_hi)
489
+ wrapping_range_format( valid_range, max_hi)
475
490
)
476
491
)
477
492
}
@@ -484,21 +499,21 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M
484
499
self . path,
485
500
format_args!(
486
501
"something that cannot possibly fail to be {}" ,
487
- wrapping_range_format( & layout . valid_range, max_hi)
502
+ wrapping_range_format( valid_range, max_hi)
488
503
)
489
504
)
490
505
}
491
506
}
492
507
Ok ( data) => data,
493
508
} ;
494
509
// Now compare. This is slightly subtle because this is a special "wrap-around" range.
495
- if wrapping_range_contains ( & layout . valid_range , bits) {
510
+ if wrapping_range_contains ( & valid_range, bits) {
496
511
Ok ( ( ) )
497
512
} else {
498
513
throw_validation_failure ! (
499
514
bits,
500
515
self . path,
501
- format_args!( "something {}" , wrapping_range_format( & layout . valid_range, max_hi) )
516
+ format_args!( "something {}" , wrapping_range_format( valid_range, max_hi) )
502
517
)
503
518
}
504
519
}
@@ -594,7 +609,8 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
594
609
595
610
// *After* all of this, check the ABI. We need to check the ABI to handle
596
611
// types like `NonNull` where the `Scalar` info is more restrictive than what
597
- // the fields say. But in most cases, this will just propagate what the fields say,
612
+ // the fields say (`rustc_layout_scalar_valid_range_start`).
613
+ // But in most cases, this will just propagate what the fields say,
598
614
// and then we want the error to point at the field -- so, first recurse,
599
615
// then check ABI.
600
616
//
@@ -603,11 +619,18 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
603
619
// MyNewtype and then the scalar in there).
604
620
match op. layout . abi {
605
621
layout:: Abi :: Uninhabited => unreachable ! ( ) , // checked above
606
- layout:: Abi :: Scalar ( ref layout) => {
607
- self . visit_scalar ( op, layout) ?;
622
+ layout:: Abi :: Scalar ( ref scalar_layout) => {
623
+ self . visit_scalar ( op, scalar_layout) ?;
624
+ }
625
+ layout:: Abi :: ScalarPair { .. } | layout:: Abi :: Vector { .. } => {
626
+ // These have fields that we already visited above, so we already checked
627
+ // all their scalar-level restrictions.
628
+ // There is also no equivalent to `rustc_layout_scalar_valid_range_start`
629
+ // that would make skipping them here an issue.
630
+ }
631
+ layout:: Abi :: Aggregate { .. } => {
632
+ // Nothing to do.
608
633
}
609
- // FIXME: Should we do something for ScalarPair? Vector?
610
- _ => { }
611
634
}
612
635
613
636
Ok ( ( ) )
0 commit comments