Skip to content

const-eval: always do mem-to-mem copies if there might be padding involved#148967

Merged
rust-bors[bot] merged 2 commits intorust-lang:mainfrom
RalfJung:const-eval-preserve-src-padding
Feb 4, 2026
Merged

const-eval: always do mem-to-mem copies if there might be padding involved#148967
rust-bors[bot] merged 2 commits intorust-lang:mainfrom
RalfJung:const-eval-preserve-src-padding

Conversation

@RalfJung
Copy link
Member

@RalfJung RalfJung commented Nov 15, 2025

This is the final piece of the puzzle for #148470: when copying data of a type that has padding, always do a mem-to-mem copy, so that we always preserve the source padding exactly. That prevents rustc implementation choices from leaking into user-visible behavior.

This is technically a breaking change: the example at the top of #148470 no longer compiles with this. However, it seems very unlikely that anyone would have depended on this. My main concern is not backwards compatibility, it is performance.

Fixes #148470


Actually that seems to be entirely fine, it even helps with some benchmarks! I guess the mem-to-mem codepath is actually faster than the scalar pair codepath for the copy itself. It can slow things down later since now we have to do everything bytewise, but that doesn't show up in our benchmarks and might not be very relevant after all (in particular, it only affects types with padding, so the rather common wide pointers still always use the efficient scalar representation).

So that would be my proposal to for resolving this issue then: to make const-eval behavior consistent, we always copy the padding from the source to the target. IOW, potentially pre-existing provenance in the target always gets overwritten (that part is already in #148259), and potentially existing provenance in padding in the source always gets carried over (that's #148967). If there's provenance elsewhere in the source our existing handling is fine:

  • If it's in an integer, that's UB during const-eval so we can do whatever.
  • If it's in a pointer, the the fragments must combine back together to a pointer or else we have UB.
  • If it's in a union we just carry it over unchanged.

@traviscross we should check that this special const-eval-only UB is properly reflected in the reference. Currently we have this but that only talks about int2ptr, not about invalid pointer fragments at pointer type. I also wonder if this shouldn't rather be part of "invalid values" to make it clear that this applies recursively inside fields as well.
EDIT: Reference PR is up at rust-lang/reference#2091.

Originally posted by @RalfJung in #148470

Worth noting that this does not resolve the concerns @theemathas had about -Zextra-const-ub-checks sometimes causing more code to compile. Specifically, with that flag, the behavior changes to "potentially existing provenance in padding in the source never gets carried over". However, it's a nightly-only flag (used by Miri) so while the behavior is odd, I don't think this is a problem.

Originally posted by @RalfJung in #148470


Related:

@rustbot
Copy link
Collaborator

rustbot commented Nov 15, 2025

Some changes occurred to the CTFE machinery

cc @RalfJung, @oli-obk, @lcnr

Some changes occurred to the CTFE / Miri interpreter

cc @rust-lang/miri

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Nov 15, 2025
@rustbot
Copy link
Collaborator

rustbot commented Nov 15, 2025

r? @JonathanBrouwer

rustbot has assigned @JonathanBrouwer.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@RalfJung
Copy link
Member Author

@bors try
@rust-timer queue

@rust-timer

This comment has been minimized.

rust-bors bot added a commit that referenced this pull request Nov 15, 2025
…try>

const-eval: always do mem-to-mem copies if there might be padding involved
@rust-bors

This comment has been minimized.

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label Nov 15, 2025
@rust-log-analyzer

This comment has been minimized.

@RalfJung RalfJung force-pushed the const-eval-preserve-src-padding branch from c4acb77 to 01194d7 Compare November 15, 2025 10:22
@rust-bors
Copy link
Contributor

rust-bors bot commented Nov 15, 2025

☀️ Try build successful (CI)
Build commit: 78c81ee (78c81ee3917a99dcff6e2e6822800f0492c415c3, parent: 733108b6d4acaa93fe26ae281ea305aacd6aac4e)

@rust-timer

This comment has been minimized.

@traviscross traviscross added the I-lang-radar Items that are on lang's radar and will need eventual work or consideration. label Nov 15, 2025
@rust-timer
Copy link
Collaborator

Finished benchmarking commit (78c81ee): comparison URL.

Overall result: ❌✅ regressions and improvements - please read the text below

Benchmarking this pull request means it may be perf-sensitive – we'll automatically label it not fit for rolling up. You can override this, but we strongly advise not to, due to possible changes in compiler perf.

Next Steps: If you can justify the regressions found in this try perf run, please do so in sufficient writing along with @rustbot label: +perf-regression-triaged. If not, please fix the regressions and do another perf run. If its results are neutral or positive, the label will be automatically removed.

@bors rollup=never
@rustbot label: -S-waiting-on-perf +perf-regression

Instruction count

Our most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
0.2% [0.0%, 0.3%] 7
Improvements ✅
(primary)
-2.8% [-2.8%, -2.8%] 1
Improvements ✅
(secondary)
-0.4% [-0.5%, -0.2%] 12
All ❌✅ (primary) -2.8% [-2.8%, -2.8%] 1

Max RSS (memory usage)

Results (primary -3.2%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
-3.2% [-3.2%, -3.2%] 1
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) -3.2% [-3.2%, -3.2%] 1

Cycles

Results (primary -2.7%, secondary -9.4%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
- - 0
Improvements ✅
(primary)
-2.7% [-2.7%, -2.7%] 1
Improvements ✅
(secondary)
-9.4% [-16.0%, -2.8%] 2
All ❌✅ (primary) -2.7% [-2.7%, -2.7%] 1

Binary size

Results (primary -1.1%, secondary 0.0%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
0.0% [0.0%, 0.0%] 1
Improvements ✅
(primary)
-1.1% [-1.1%, -1.1%] 1
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) -1.1% [-1.1%, -1.1%] 1

Bootstrap: 472.272s -> 472.014s (-0.05%)
Artifact size: 388.64 MiB -> 388.68 MiB (0.01%)

@rustbot rustbot added perf-regression Performance regression. and removed S-waiting-on-perf Status: Waiting on a perf run to be completed. labels Nov 15, 2025
@RalfJung
Copy link
Member Author

RalfJung commented Nov 15, 2025 via email

@craterbot
Copy link
Collaborator

👌 Experiment pr-148967 created and queued.
🤖 Automatically detected try build 78c81ee
⚠️ Try build based on commit c4acb77, but latest commit is 01194d7. Did you forget to make a new try build?
🔍 You can check out the queue and this experiment's details.

ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@craterbot craterbot added S-waiting-on-crater Status: Waiting on a crater run to be completed. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Nov 15, 2025
@RalfJung RalfJung force-pushed the const-eval-preserve-src-padding branch from 01194d7 to 472364c Compare November 16, 2025 10:29
@rustbot

This comment has been minimized.

@traviscross traviscross added needs-fcp This change is insta-stable, or significant enough to need a team FCP to proceed. I-lang-nominated Nominated for discussion during a lang team meeting. P-lang-drag-1 Lang team prioritization drag level 1. https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang T-lang Relevant to the language team labels Nov 16, 2025
@theemathas
Copy link
Contributor

Most of the performance regressions are from the coercions benchmark. All it does is create an array of a large number of string literals in const. Why did this benchmark's performance regress? There is no padding involved in any of the types.

traviscross added a commit to RalfJung/reference that referenced this pull request Jan 27, 2026
Let's add examples and explanatory notes to clarify the restriction
that the representation of the final value of a constant or static
initializer must only contain bytes with provenance in whole-pointer
groups.

We'll add a `compile_fail` example demonstrating how storing a pointer
that extends into padding creates pointer fragments in the final
value, causing compilation to fail and show to work around this by
explicitly zeroing the padding bytes.

Let's extend the existing note about uninitialized padding bytes to
provide deeper intuition about this restriction and explain how
constant evaluation makes the details of typed copies
observable (whether field-by-field or memory-block), how these details
are not yet fully specified in Rust, and why the compiler must be
allowed to reject initializers with uninitialized padding bytes to
preserve future flexibility (such as always setting padding to
uninitialized).

Context: rust-lang/rust#148470, rust-lang/rust#148967
traviscross added a commit to RalfJung/reference that referenced this pull request Jan 27, 2026
Let's add examples and explanatory notes to clarify the restriction
that the representation of the final value of a constant or static
initializer must only contain bytes with provenance in whole-pointer
groups.

We'll add a `compile_fail` example demonstrating how storing a pointer
that extends into padding creates pointer fragments in the final
value, causing compilation to fail and show to work around this by
explicitly zeroing the padding bytes.

Let's extend the existing note about uninitialized padding bytes to
provide deeper intuition about this restriction and explain how
constant evaluation makes the details of typed copies
observable (whether field-by-field or memory-block), how these details
are not yet fully specified in Rust, and why the compiler must be
allowed to reject initializers with uninitialized padding bytes to
preserve future flexibility (such as always setting padding to
uninitialized).

Context: rust-lang/rust#148470, rust-lang/rust#148967
traviscross added a commit to RalfJung/reference that referenced this pull request Jan 27, 2026
Let's add examples and explanatory notes to clarify the restriction
that the representation of the final value of a constant or static
initializer must only contain bytes with provenance in whole-pointer
groups.

We'll add a `compile_fail` example demonstrating how storing a pointer
that extends into padding creates pointer fragments in the final
value, causing compilation to fail and show to work around this by
explicitly zeroing the padding bytes.

Let's extend the existing note about uninitialized padding bytes to
provide deeper intuition about this restriction and explain how
constant evaluation makes the details of typed copies
observable (whether field-by-field or memory-block), how these details
are not yet fully specified in Rust, and why the compiler must be
allowed to reject initializers with uninitialized padding bytes to
preserve future flexibility (such as always setting padding to
uninitialized).

Context: rust-lang/rust#148470, rust-lang/rust#148967
traviscross added a commit to RalfJung/reference that referenced this pull request Jan 27, 2026
Let's add examples and explanatory notes to clarify the restriction
that the representation of the final value of a constant or static
initializer must only contain bytes with provenance in whole-pointer
groups.

We'll add a `compile_fail` example demonstrating how storing a pointer
that extends into padding creates pointer fragments in the final
value, causing compilation to fail and show to work around this by
explicitly zeroing the padding bytes.

Let's extend the existing note about uninitialized padding bytes to
provide deeper intuition about this restriction and explain how
constant evaluation makes the details of typed copies
observable (whether field-by-field or memory-block), how these details
are not yet fully specified in Rust, and why the compiler must be
allowed to reject initializers with uninitialized padding bytes to
preserve future flexibility (such as always setting padding to
uninitialized).

Context: rust-lang/rust#148470, rust-lang/rust#148967
@apiraino apiraino removed the to-announce Announce this issue on triage meeting label Jan 29, 2026
traviscross added a commit to RalfJung/reference that referenced this pull request Feb 3, 2026
Let's add examples and explanatory notes to clarify the restriction
that the representation of the final value of a constant or static
initializer must only contain bytes with provenance in whole-pointer
groups.

We'll add a `compile_fail` example demonstrating how storing a pointer
that extends into padding creates pointer fragments in the final
value, causing compilation to fail and show to work around this by
explicitly zeroing the padding bytes.

Let's extend the existing note about uninitialized padding bytes to
provide deeper intuition about this restriction and explain how
constant evaluation makes the details of typed copies
observable (whether field-by-field or memory-block), how these details
are not yet fully specified in Rust, and why the compiler must be
allowed to reject initializers with uninitialized padding bytes to
preserve future flexibility (such as always setting padding to
uninitialized).

Context:

- rust-lang/rust#148470
- rust-lang/rust#148967
@traviscross
Copy link
Contributor

@rustbot labels -S-waiting-on-documentation

We've approved the corresponding Reference PR and the lang FCP is complete. This is now OK to go forward as a lang matter. Based on the earlier review (and that it looks OK to me too):

@bors r=JonathanBrouwer,traviscross

@rust-bors
Copy link
Contributor

rust-bors bot commented Feb 3, 2026

📌 Commit 5a76a60 has been approved by JonathanBrouwer,traviscross

It is now in the queue for this repository.

@rustbot rustbot removed the S-waiting-on-documentation Status: Waiting on approved PRs to documentation before merging label Feb 3, 2026
@rust-bors rust-bors bot added the S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. label Feb 3, 2026
@traviscross
Copy link
Contributor

@bors rollup

traviscross added a commit to RalfJung/reference that referenced this pull request Feb 3, 2026
Let's add examples and explanatory notes to clarify the restriction
that the representation of the final value of a constant or static
initializer must only contain bytes with provenance in whole-pointer
groups.

We'll add a `compile_fail` example demonstrating how storing a pointer
that extends into padding creates pointer fragments in the final
value, causing compilation to fail and show to work around this by
explicitly zeroing the padding bytes.

Let's extend the existing note about uninitialized padding bytes to
provide deeper intuition about this restriction and explain how
constant evaluation makes the details of typed copies
observable (whether field-by-field or memory-block), how these details
are not yet fully specified in Rust, and why the compiler must be
allowed to reject initializers with uninitialized padding bytes to
preserve future flexibility (such as always setting padding to
uninitialized).

Context:

- rust-lang/rust#148470
- rust-lang/rust#148967
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Feb 3, 2026
…adding, r=JonathanBrouwer,traviscross

const-eval: always do mem-to-mem copies if there might be padding involved

This is the final piece of the puzzle for rust-lang#148470: when copying data of a type that has padding, always do a mem-to-mem copy, so that we always preserve the source padding exactly. That prevents rustc implementation choices from leaking into user-visible behavior.

This is technically a breaking change: the example at the top of rust-lang#148470 no longer compiles with this. However, it seems very unlikely that anyone would have depended on this. My main concern is not backwards compatibility, it is performance.

Fixes rust-lang#148470

---

> Actually that seems to be entirely fine, it even helps with some benchmarks! I guess the mem-to-mem codepath is actually faster than the scalar pair codepath for the copy itself. It can slow things down later since now we have to do everything bytewise, but that doesn't show up in our benchmarks and might not be very relevant after all (in particular, it only affects types with padding, so the rather common wide pointers still always use the efficient scalar representation).
>
> So that would be my proposal to for resolving this issue then: to make const-eval behavior consistent, we always copy the padding from the source to the target. IOW, potentially pre-existing provenance in the target always gets overwritten (that part is already in rust-lang#148259), and potentially existing provenance in padding in the source always gets carried over (that's rust-lang#148967). If there's provenance elsewhere in the source our existing handling is fine:
> - If it's in an integer, that's UB during const-eval so we can do whatever.
> - If it's in a pointer, the the fragments must combine back together to a pointer or else we have UB.
> - If it's in a union we just carry it over unchanged.
>
> @traviscross we should check that this special const-eval-only UB is properly reflected in the reference. Currently we have [this](https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html#r-undefined.const-transmute-ptr2int) but that only talks about int2ptr, not about invalid pointer fragments at pointer type. I also wonder if this shouldn't rather be part of ["invalid values"](https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html#r-undefined.validity) to make it clear that this applies recursively inside fields as well.
> EDIT: Reference PR is up at rust-lang/reference#2091.

 _Originally posted by @RalfJung in [rust-lang#148470](rust-lang#148470 (comment)

> Worth noting that this does not resolve the concerns @theemathas had about `-Zextra-const-ub-checks` sometimes causing *more* code to compile. Specifically, with that flag, the behavior changes to "potentially existing provenance in padding in the source never gets carried over". However, it's a nightly-only flag (used by Miri) so while the behavior is odd, I don't think this is a problem.

 _Originally posted by @RalfJung in [rust-lang#148470](rust-lang#148470 (comment)

---

Related:

- rust-lang#148470
- rust-lang/reference#2091
rust-bors bot pushed a commit that referenced this pull request Feb 4, 2026
…uwer

Rollup of 7 pull requests

Successful merges:

 - #148967 (const-eval: always do mem-to-mem copies if there might be padding involved)
 - #152012 (Use `DEVELOPER_DIR` instead of a custom `xcode-select` script)
 - #152044 (Convert to inline diagnostics in `rustc_incremental`)
 - #152046 (Use glob imports for attribute parsers)
 - #152054 (Distinguish error message for `#[diagnostic::on_const]` on const trait impls)
 - #152059 (Fix some autodiff tests require Clto=fat)
 - #152073 (Convert to inline diagnostics in `rustc_mir_dataflow`)
@rust-bors rust-bors bot merged commit bfc6249 into rust-lang:main Feb 4, 2026
11 checks passed
@rustbot rustbot added this to the 1.95.0 milestone Feb 4, 2026
rust-timer added a commit that referenced this pull request Feb 4, 2026
Rollup merge of #148967 - RalfJung:const-eval-preserve-src-padding, r=JonathanBrouwer,traviscross

const-eval: always do mem-to-mem copies if there might be padding involved

This is the final piece of the puzzle for #148470: when copying data of a type that has padding, always do a mem-to-mem copy, so that we always preserve the source padding exactly. That prevents rustc implementation choices from leaking into user-visible behavior.

This is technically a breaking change: the example at the top of #148470 no longer compiles with this. However, it seems very unlikely that anyone would have depended on this. My main concern is not backwards compatibility, it is performance.

Fixes #148470

---

> Actually that seems to be entirely fine, it even helps with some benchmarks! I guess the mem-to-mem codepath is actually faster than the scalar pair codepath for the copy itself. It can slow things down later since now we have to do everything bytewise, but that doesn't show up in our benchmarks and might not be very relevant after all (in particular, it only affects types with padding, so the rather common wide pointers still always use the efficient scalar representation).
>
> So that would be my proposal to for resolving this issue then: to make const-eval behavior consistent, we always copy the padding from the source to the target. IOW, potentially pre-existing provenance in the target always gets overwritten (that part is already in #148259), and potentially existing provenance in padding in the source always gets carried over (that's #148967). If there's provenance elsewhere in the source our existing handling is fine:
> - If it's in an integer, that's UB during const-eval so we can do whatever.
> - If it's in a pointer, the the fragments must combine back together to a pointer or else we have UB.
> - If it's in a union we just carry it over unchanged.
>
> @traviscross we should check that this special const-eval-only UB is properly reflected in the reference. Currently we have [this](https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html#r-undefined.const-transmute-ptr2int) but that only talks about int2ptr, not about invalid pointer fragments at pointer type. I also wonder if this shouldn't rather be part of ["invalid values"](https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html#r-undefined.validity) to make it clear that this applies recursively inside fields as well.
> EDIT: Reference PR is up at rust-lang/reference#2091.

 _Originally posted by @RalfJung in [#148470](#148470 (comment)

> Worth noting that this does not resolve the concerns @theemathas had about `-Zextra-const-ub-checks` sometimes causing *more* code to compile. Specifically, with that flag, the behavior changes to "potentially existing provenance in padding in the source never gets carried over". However, it's a nightly-only flag (used by Miri) so while the behavior is odd, I don't think this is a problem.

 _Originally posted by @RalfJung in [#148470](#148470 (comment)

---

Related:

- #148470
- rust-lang/reference#2091
traviscross added a commit to RalfJung/reference that referenced this pull request Feb 4, 2026
Let's add examples and explanatory notes to clarify the restriction
that the representation of the final value of a constant or static
initializer must only contain bytes with provenance in whole-pointer
groups.

We'll add a `compile_fail` example demonstrating how storing a pointer
that extends into padding creates pointer fragments in the final
value, causing compilation to fail and show to work around this by
explicitly zeroing the padding bytes.

Let's extend the existing note about uninitialized padding bytes to
provide deeper intuition about this restriction and explain how
constant evaluation makes the details of typed copies
observable (whether field-by-field or memory-block), how these details
are not yet fully specified in Rust, and why the compiler must be
allowed to reject initializers with uninitialized padding bytes to
preserve future flexibility (such as always setting padding to
uninitialized).

Context:

- rust-lang/rust#148470
- rust-lang/rust#148967
traviscross added a commit to RalfJung/reference that referenced this pull request Feb 4, 2026
Let's add examples and explanatory notes to clarify the restriction
that the representation of the final value of a constant or static
initializer must only contain bytes with provenance in whole-pointer
groups.

We'll add a `compile_fail` example demonstrating how storing a pointer
that extends into padding creates pointer fragments in the final
value, causing compilation to fail and show to work around this by
explicitly zeroing the padding bytes.

Let's extend the existing note about uninitialized padding bytes to
provide deeper intuition about this restriction and explain how
constant evaluation makes the details of typed copies
observable (whether field-by-field or memory-block), how these details
are not yet fully specified in Rust, and why the compiler must be
allowed to reject initializers with uninitialized padding bytes to
preserve future flexibility (such as always setting padding to
uninitialized).

Context:

- rust-lang/rust#148470
- rust-lang/rust#148967
traviscross added a commit to RalfJung/reference that referenced this pull request Feb 4, 2026
Let's add examples and explanatory notes to clarify the restriction
that the representation of the final value of a constant or static
initializer must only contain bytes with provenance in whole-pointer
groups.

We'll add a `compile_fail` example demonstrating how storing a pointer
that extends into padding creates pointer fragments in the final
value, causing compilation to fail and show to work around this by
explicitly zeroing the padding bytes.

Let's extend the existing note about uninitialized padding bytes to
provide deeper intuition about this restriction and explain how
constant evaluation makes the details of typed copies
observable (whether field-by-field or memory-block), how these details
are not yet fully specified in Rust, and why the compiler must be
allowed to reject initializers with uninitialized padding bytes to
preserve future flexibility (such as always setting padding to
uninitialized).

Context:

- rust-lang/rust#148470
- rust-lang/rust#148967
traviscross added a commit to RalfJung/reference that referenced this pull request Feb 4, 2026
Let's add examples and explanatory notes to clarify the restriction
that the representation of the final value of a constant or static
initializer must only contain bytes with provenance in whole-pointer
groups.

We'll add a `compile_fail` example demonstrating how storing a pointer
that extends into padding creates pointer fragments in the final
value, causing compilation to fail and show to work around this by
explicitly zeroing the padding bytes.

Let's extend the existing note about uninitialized padding bytes to
provide deeper intuition about this restriction and explain how
constant evaluation makes the details of typed copies
observable (whether field-by-field or memory-block), how these details
are not yet fully specified in Rust, and why the compiler must be
allowed to reject initializers with uninitialized padding bytes to
preserve future flexibility (such as always setting padding to
uninitialized).

Context:

- rust-lang/rust#148470
- rust-lang/rust#148967
@JonathanBrouwer
Copy link
Contributor

@rust-timer build 67ecc0e

@rust-timer

This comment has been minimized.

traviscross added a commit to RalfJung/reference that referenced this pull request Feb 4, 2026
Let's add examples and explanatory notes to clarify the restriction
that the representation of the final value of a constant or static
initializer must only contain bytes with provenance in whole-pointer
groups.

We'll add a `compile_fail` example demonstrating how storing a pointer
that extends into padding creates pointer fragments in the final
value, causing compilation to fail and show to work around this by
explicitly zeroing the padding bytes.

Let's extend the existing note about uninitialized padding bytes to
provide deeper intuition about this restriction and explain how
constant evaluation makes the details of typed copies
observable (whether field-by-field or memory-block), how these details
are not yet fully specified in Rust, and why the compiler must be
allowed to reject initializers with uninitialized padding bytes to
preserve future flexibility (such as always setting padding to
uninitialized).

Context:

- rust-lang/rust#148470
- rust-lang/rust#148967
traviscross added a commit to RalfJung/reference that referenced this pull request Feb 4, 2026
Let's add examples and explanatory notes to clarify the restriction
that the representation of the final value of a constant or static
initializer must only contain bytes with provenance in whole-pointer
groups.

We'll add a `compile_fail` example demonstrating how storing a pointer
that extends into padding creates pointer fragments in the final
value, causing compilation to fail and show to work around this by
explicitly zeroing the padding bytes.

Let's extend the existing note about uninitialized padding bytes to
provide deeper intuition about this restriction and explain how
constant evaluation makes the details of typed copies
observable (whether field-by-field or memory-block), how these details
are not yet fully specified in Rust, and why the compiler must be
allowed to reject initializers with uninitialized padding bytes to
preserve future flexibility (such as always setting padding to
uninitialized).

Context:

- rust-lang/rust#148470
- rust-lang/rust#148967
@rust-timer
Copy link
Collaborator

Finished benchmarking commit (67ecc0e): comparison URL.

Overall result: ❌✅ regressions and improvements - please read the text below

Benchmarking this pull request means it may be perf-sensitive – we'll automatically label it not fit for rolling up. You can override this, but we strongly advise not to, due to possible changes in compiler perf.

Next Steps: If you can justify the regressions found in this try perf run, please do so in sufficient writing along with @rustbot label: +perf-regression-triaged. If not, please fix the regressions and do another perf run. If its results are neutral or positive, the label will be automatically removed.

@bors rollup=never
@rustbot label: -S-waiting-on-perf +perf-regression

Instruction count

Our most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
0.9% [0.2%, 1.4%] 9
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-0.3% [-0.4%, -0.3%] 9
All ❌✅ (primary) - - 0

Max RSS (memory usage)

Results (secondary 4.3%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
4.3% [2.1%, 6.4%] 2
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
- - 0
All ❌✅ (primary) - - 0

Cycles

Results (secondary -0.7%)

A less reliable metric. May be of interest, but not used to determine the overall result above.

mean range count
Regressions ❌
(primary)
- - 0
Regressions ❌
(secondary)
3.2% [1.6%, 4.6%] 3
Improvements ✅
(primary)
- - 0
Improvements ✅
(secondary)
-4.5% [-5.2%, -3.6%] 3
All ❌✅ (primary) - - 0

Binary size

This benchmark run did not return any relevant results for this metric.

Bootstrap: 475.191s -> 477.005s (0.38%)
Artifact size: 397.77 MiB -> 397.75 MiB (-0.01%)

@JonathanBrouwer
Copy link
Contributor

Sadly perf is a bit more negative than it was before.
Since it's not that bad, and only affects secondary benchmarks, I'd propose to just accept it

@RalfJung RalfJung deleted the const-eval-preserve-src-padding branch February 5, 2026 07:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. finished-final-comment-period The final comment period is finished for this PR / Issue. I-lang-radar Items that are on lang's radar and will need eventual work or consideration. needs-fcp This change is insta-stable, or significant enough to need a team FCP to proceed. perf-regression Performance regression. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Partial pointers in padding can make const-eval fail