@@ -629,11 +629,24 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
629629 op : & OpTy < ' tcx , M :: PointerTag > ,
630630 scalar_layout : ScalarAbi ,
631631 ) -> 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 {
633646 // Nothing to check
634647 return Ok ( ( ) ) ;
635648 }
636- // At least one value is excluded .
649+ // We have something to check .
637650 let valid_range = scalar_layout. valid_range ( self . ecx ) ;
638651 let WrappingRange { start, end } = valid_range;
639652 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, '
647660 expected { "something {}" , wrapping_range_format( valid_range, max_value) } ,
648661 ) ;
649662 let bits = match value. try_to_int ( ) {
663+ Ok ( int) => int. assert_bits ( op. layout . size ) ,
650664 Err ( _) => {
651665 // So this is a pointer then, and casting to an int failed.
652666 // Can only happen during CTFE.
667+ // We support 2 kinds of ranges here: full range, and excluding zero.
653668 if start == 1 && end == max_value {
654669 // Only null is the niche. So make sure the ptr is NOT null.
655670 if self . ecx . scalar_may_be_null ( value) {
@@ -660,7 +675,11 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
660675 wrapping_range_format( valid_range, max_value)
661676 }
662677 )
678+ } else {
679+ return Ok ( ( ) ) ;
663680 }
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.)
664683 return Ok ( ( ) ) ;
665684 } else {
666685 // 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, '
674693 )
675694 }
676695 }
677- Ok ( int) => int. assert_bits ( op. layout . size ) ,
678696 } ;
679- // Now compare. This is slightly subtle because this is a special "wrap-around" range.
697+ // Now compare.
680698 if valid_range. contains ( bits) {
681699 Ok ( ( ) )
682700 } else {
0 commit comments