@@ -629,11 +629,24 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
629
629
op : & OpTy < ' tcx , M :: PointerTag > ,
630
630
scalar_layout : ScalarAbi ,
631
631
) -> InterpResult < ' tcx > {
632
- if scalar_layout. valid_range ( self . ecx ) . is_full_for ( op. layout . size ) {
632
+ // We check `is_full_range` in a slightly complicated way because *if* we are checking
633
+ // number validity, then we want to ensure that `Scalar::Initialized` is indeed initialized,
634
+ // i.e. that we go over the `check_init` below.
635
+ let is_full_range = match scalar_layout {
636
+ ScalarAbi :: Initialized { valid_range, .. } => {
637
+ if M :: enforce_number_validity ( self . ecx ) {
638
+ false // not "full" since uninit is not accepted
639
+ } else {
640
+ valid_range. is_full_for ( op. layout . size )
641
+ }
642
+ }
643
+ ScalarAbi :: Union { .. } => true ,
644
+ } ;
645
+ if is_full_range {
633
646
// Nothing to check
634
647
return Ok ( ( ) ) ;
635
648
}
636
- // At least one value is excluded .
649
+ // We have something to check .
637
650
let valid_range = scalar_layout. valid_range ( self . ecx ) ;
638
651
let WrappingRange { start, end } = valid_range;
639
652
let max_value = op. layout . size . unsigned_int_max ( ) ;
@@ -647,9 +660,11 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
647
660
expected { "something {}" , wrapping_range_format( valid_range, max_value) } ,
648
661
) ;
649
662
let bits = match value. try_to_int ( ) {
663
+ Ok ( int) => int. assert_bits ( op. layout . size ) ,
650
664
Err ( _) => {
651
665
// So this is a pointer then, and casting to an int failed.
652
666
// Can only happen during CTFE.
667
+ // We support 2 kinds of ranges here: full range, and excluding zero.
653
668
if start == 1 && end == max_value {
654
669
// Only null is the niche. So make sure the ptr is NOT null.
655
670
if self . ecx . scalar_may_be_null ( value) {
@@ -660,7 +675,11 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
660
675
wrapping_range_format( valid_range, max_value)
661
676
}
662
677
)
678
+ } else {
679
+ return Ok ( ( ) ) ;
663
680
}
681
+ } else if scalar_layout. valid_range ( self . ecx ) . is_full_for ( op. layout . size ) {
682
+ // Easy. (This is reachable if `enforce_number_validity` is set.)
664
683
return Ok ( ( ) ) ;
665
684
} else {
666
685
// Conservatively, we reject, because the pointer *could* have a bad
@@ -674,9 +693,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
674
693
)
675
694
}
676
695
}
677
- Ok ( int) => int. assert_bits ( op. layout . size ) ,
678
696
} ;
679
- // Now compare. This is slightly subtle because this is a special "wrap-around" range.
697
+ // Now compare.
680
698
if valid_range. contains ( bits) {
681
699
Ok ( ( ) )
682
700
} else {
0 commit comments