@@ -1442,7 +1442,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
14421442 // First check that the base type is valid
14431443 self . visit_value ( & val. transmute ( self . ecx . layout_of ( * base) ?, self . ecx ) ?) ?;
14441444 // When you extend this match, make sure to also add tests to
1445- // tests/ui/type/pattern_types/validity.rs((
1445+ // tests/ui/type/pattern_types/validity.rs
14461446 match * * pat {
14471447 // Range and non-null patterns are precisely reflected into `valid_range` and thus
14481448 // handled fully by `visit_scalar` (called below).
@@ -1457,6 +1457,37 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
14571457 // we won't see optimizations actually breaking such programs.
14581458 ty:: PatternKind :: Or ( _patterns) => { }
14591459 }
1460+ match val. layout . backend_repr {
1461+ BackendRepr :: Scalar ( scalar_layout) => {
1462+ if !scalar_layout. is_uninit_valid ( ) {
1463+ // There is something to check here.
1464+ // We read directly via `ecx` since the read cannot fail -- we already read
1465+ // this field above when recursing into the field.
1466+ let scalar = self . ecx . read_scalar ( val) ?;
1467+ self . visit_scalar ( scalar, scalar_layout) ?;
1468+ }
1469+ }
1470+ BackendRepr :: ScalarPair ( a_layout, b_layout) => {
1471+ // We can only proceed if *both* scalars need to be initialized.
1472+ // FIXME: find a way to also check ScalarPair when one side can be uninit but
1473+ // the other must be init.
1474+ if !a_layout. is_uninit_valid ( ) && !b_layout. is_uninit_valid ( ) {
1475+ // We read directly via `ecx` since the read cannot fail -- we already read
1476+ // this field above when recursing into the field.
1477+ let ( a, b) = self . ecx . read_immediate ( val) ?. to_scalar_pair ( ) ;
1478+ self . visit_scalar ( a, a_layout) ?;
1479+ self . visit_scalar ( b, b_layout) ?;
1480+ }
1481+ }
1482+ BackendRepr :: SimdVector { .. } | BackendRepr :: SimdScalableVector { .. } => {
1483+ // No checks here, we assume layout computation gets this right.
1484+ // (This is harder to check since Miri does not represent these as `Immediate`. We
1485+ // also cannot use field projections since this might be a newtype around a vector.)
1486+ }
1487+ BackendRepr :: Memory { .. } => {
1488+ // Nothing to do.
1489+ }
1490+ }
14601491 }
14611492 ty:: Adt ( adt, _) if adt. is_maybe_dangling ( ) => {
14621493 let old_may_dangle = mem:: replace ( & mut self . may_dangle , true ) ;
@@ -1479,53 +1510,21 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
14791510 }
14801511 }
14811512
1482- // *After* all of this, check further information stored in the layout. We need to check
1483- // this to handle types like `NonNull` where the `Scalar` info is more restrictive than what
1484- // the fields say (`rustc_layout_scalar_valid_range_start`). But in most cases, this will
1485- // just propagate what the fields say, and then we want the error to point at the field --
1486- // so, we first recurse, then we do this check.
1513+ // *After* all of this, check further information stored in the layout.
1514+ // On leaf types like `!` or empty enums, this will raise the error.
1515+ // This means that for types wrapping such a type, we won't ever get here, but it's
1516+ // just the simplest way to check for this case.
14871517 //
14881518 // FIXME: We could avoid some redundant checks here. For newtypes wrapping
14891519 // scalars, we do the same check on every "level" (e.g., first we check
1490- // MyNewtype and then the scalar in there ).
1520+ // the fields of MyNewtype, and then we check MyNewType again ).
14911521 if val. layout . is_uninhabited ( ) {
14921522 let ty = val. layout . ty ;
14931523 throw_validation_failure ! (
14941524 self . path,
14951525 format!( "encountered a value of uninhabited type `{ty}`" )
14961526 ) ;
14971527 }
1498- match val. layout . backend_repr {
1499- BackendRepr :: Scalar ( scalar_layout) => {
1500- if !scalar_layout. is_uninit_valid ( ) {
1501- // There is something to check here.
1502- // We read directly via `ecx` since the read cannot fail -- we already read
1503- // this field above when recursing into the field.
1504- let scalar = self . ecx . read_scalar ( val) ?;
1505- self . visit_scalar ( scalar, scalar_layout) ?;
1506- }
1507- }
1508- BackendRepr :: ScalarPair ( a_layout, b_layout) => {
1509- // We can only proceed if *both* scalars need to be initialized.
1510- // FIXME: find a way to also check ScalarPair when one side can be uninit but
1511- // the other must be init.
1512- if !a_layout. is_uninit_valid ( ) && !b_layout. is_uninit_valid ( ) {
1513- // We read directly via `ecx` since the read cannot fail -- we already read
1514- // this field above when recursing into the field.
1515- let ( a, b) = self . ecx . read_immediate ( val) ?. to_scalar_pair ( ) ;
1516- self . visit_scalar ( a, a_layout) ?;
1517- self . visit_scalar ( b, b_layout) ?;
1518- }
1519- }
1520- BackendRepr :: SimdVector { .. } | BackendRepr :: SimdScalableVector { .. } => {
1521- // No checks here, we assume layout computation gets this right.
1522- // (This is harder to check since Miri does not represent these as `Immediate`. We
1523- // also cannot use field projections since this might be a newtype around a vector.)
1524- }
1525- BackendRepr :: Memory { .. } => {
1526- // Nothing to do.
1527- }
1528- }
15291528
15301529 interp_ok ( ( ) )
15311530 }
0 commit comments