@@ -272,7 +272,8 @@ struct ValidityVisitor<'rt, 'tcx, M: Machine<'tcx>> {
272272 ctfe_mode : Option < CtfeValidationMode > ,
273273 ecx : & ' rt mut InterpCx < ' tcx , M > ,
274274 /// Whether provenance should be reset outside of pointers (emulating the effect of a typed
275- /// copy).
275+ /// copy). If this is `true`, then `M::RESET_PROVENANCE_AND_PADDING` is true, but not vice
276+ /// versa since we don't want to reset adding for recursive validation.
276277 reset_provenance_and_padding : bool ,
277278 /// This tracks which byte ranges in this value contain data; the remaining bytes are padding.
278279 /// The ideal representation here would be pointer-length pairs, but to keep things more compact
@@ -416,7 +417,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
416417 let imm = self . read_immediate ( val, expected) ?;
417418 // Reset provenance: ensure slice tail metadata does not preserve provenance,
418419 // and ensure all pointers do not preserve partial provenance.
419- if self . reset_provenance_and_padding {
420+ if self . reset_provenance_and_padding ( ) {
420421 if matches ! ( imm. layout. abi, Abi :: Scalar ( ..) ) {
421422 // A thin pointer. If it has provenance, we don't have to do anything.
422423 // If it does not, ensure we clear the provenance in memory.
@@ -676,7 +677,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
676677 value: format!( "{scalar:x}" ) ,
677678 }
678679 ) ;
679- if self . reset_provenance_and_padding {
680+ if self . reset_provenance_and_padding ( ) {
680681 self . ecx . clear_provenance ( value) ?;
681682 self . add_data_range_place ( value) ;
682683 }
@@ -691,7 +692,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
691692 value: format!( "{scalar:x}" ) ,
692693 }
693694 ) ;
694- if self . reset_provenance_and_padding {
695+ if self . reset_provenance_and_padding ( ) {
695696 self . ecx . clear_provenance ( value) ?;
696697 self . add_data_range_place ( value) ;
697698 }
@@ -708,7 +709,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
708709 ExpectedKind :: Int
709710 } ,
710711 ) ?;
711- if self . reset_provenance_and_padding {
712+ if self . reset_provenance_and_padding ( ) {
712713 self . ecx . clear_provenance ( value) ?;
713714 self . add_data_range_place ( value) ;
714715 }
@@ -744,7 +745,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
744745 throw_validation_failure ! ( self . path, NullFnPtr ) ;
745746 }
746747 }
747- if self . reset_provenance_and_padding {
748+ if self . reset_provenance_and_padding ( ) {
748749 // Make sure we do not preserve partial provenance. This matches the thin
749750 // pointer handling in `deref_pointer`.
750751 if matches ! ( scalar, Scalar :: Int ( ..) ) {
@@ -847,6 +848,13 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
847848 }
848849 }
849850
851+ #[ inline( always) ]
852+ fn reset_provenance_and_padding ( & self ) -> bool {
853+ // Make sure this becomes a constant `false` when `M::RESET_PADDING_AND_PROVENANCE` is `false`.
854+ // This way, all the padding/provenance reset code paths can be removed in the CTFE machine.
855+ M :: RESET_PROVENANCE_AND_PADDING && self . reset_provenance_and_padding
856+ }
857+
850858 /// Add the given pointer-length pair to the "data" range of this visit.
851859 fn add_data_range ( & mut self , ptr : Pointer < Option < M :: Provenance > > , size : Size ) {
852860 if let Some ( data_bytes) = self . data_bytes . as_mut ( ) {
@@ -882,6 +890,9 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
882890 }
883891
884892 fn reset_padding ( & mut self , place : & PlaceTy < ' tcx , M :: Provenance > ) -> InterpResult < ' tcx > {
893+ if !M :: RESET_PROVENANCE_AND_PADDING {
894+ return Ok ( ( ) ) ;
895+ }
885896 let Some ( data_bytes) = self . data_bytes . as_mut ( ) else { return Ok ( ( ) ) } ;
886897 // Our value must be in memory, otherwise we would not have set up `data_bytes`.
887898 let mplace = self . ecx . force_allocation ( place) ?;
@@ -1122,7 +1133,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
11221133 }
11231134 }
11241135 }
1125- if self . reset_provenance_and_padding
1136+ if self . reset_provenance_and_padding ( )
11261137 && let Some ( data_bytes) = self . data_bytes . as_mut ( )
11271138 {
11281139 let base_offset = Self :: data_range_offset ( self . ecx , val) ;
@@ -1255,7 +1266,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
12551266
12561267 // Don't forget that these are all non-pointer types, and thus do not preserve
12571268 // provenance.
1258- if self . reset_provenance_and_padding {
1269+ if self . reset_provenance_and_padding ( ) {
12591270 // We can't share this with above as above, we might be looking at read-only memory.
12601271 let mut alloc = self . ecx . get_ptr_alloc_mut ( mplace. ptr ( ) , size) ?. expect ( "we already excluded size 0" ) ;
12611272 alloc. clear_provenance ( ) ?;
@@ -1346,6 +1357,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
13461357
13471358 // Run the visitor.
13481359 match self . run_for_validation ( |ecx| {
1360+ if reset_provenance_and_padding {
1361+ // Check the invariant relating `reset_provenance_and_padding` to this constant.
1362+ assert ! ( M :: RESET_PROVENANCE_AND_PADDING ) ;
1363+ }
13491364 let reset_padding = reset_provenance_and_padding && {
13501365 // Check if `val` is actually stored in memory. If not, padding is not even
13511366 // represented and we need not reset it.
@@ -1409,7 +1424,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
14091424 path,
14101425 Some ( ref_tracking) ,
14111426 Some ( ctfe_mode) ,
1412- /*reset_provenance */ false ,
1427+ /*reset_provenance_and_padding */ false ,
14131428 )
14141429 }
14151430
@@ -1421,7 +1436,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
14211436 & mut self ,
14221437 val : & PlaceTy < ' tcx , M :: Provenance > ,
14231438 recursive : bool ,
1424- reset_provenance_and_padding : bool ,
14251439 ) -> InterpResult < ' tcx > {
14261440 // Note that we *could* actually be in CTFE here with `-Zextra-const-ub-checks`, but it's
14271441 // still correct to not use `ctfe_mode`: that mode is for validation of the final constant
@@ -1432,7 +1446,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
14321446 vec ! [ ] ,
14331447 None ,
14341448 None ,
1435- reset_provenance_and_padding ,
1449+ M :: RESET_PROVENANCE_AND_PADDING ,
14361450 ) ;
14371451 }
14381452 // Do a recursive check.
@@ -1442,7 +1456,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
14421456 vec ! [ ] ,
14431457 Some ( & mut ref_tracking) ,
14441458 None ,
1445- reset_provenance_and_padding ,
1459+ M :: RESET_PROVENANCE_AND_PADDING ,
14461460 ) ?;
14471461 while let Some ( ( mplace, path) ) = ref_tracking. todo . pop ( ) {
14481462 // Things behind reference do *not* have the provenance reset.
0 commit comments