const-eval: always do mem-to-mem copies if there might be padding involved#148967
Conversation
|
rustbot has assigned @JonathanBrouwer. Use |
|
@bors try |
This comment has been minimized.
This comment has been minimized.
…try> const-eval: always do mem-to-mem copies if there might be padding involved
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
c4acb77 to
01194d7
Compare
This comment has been minimized.
This comment has been minimized.
|
Finished benchmarking commit (78c81ee): comparison URL. Overall result: ❌✅ regressions and improvements - please read the text belowBenchmarking 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 @bors rollup=never Instruction countOur most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.
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.
CyclesResults (primary -2.7%, secondary -9.4%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Binary sizeResults (primary -1.1%, secondary 0.0%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Bootstrap: 472.272s -> 472.014s (-0.05%) |
|
Uh okay I guess this is actually good for perf.^^ At least for the benchmarks we have. The copy apparently gets a little cheaper, but we force more things to use the less efficient in-memory representation. The latter just does not seem to matter in our benchmarks.
Just to be safe:
@craterbot check
|
|
👌 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
01194d7 to
472364c
Compare
This comment has been minimized.
This comment has been minimized.
|
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. |
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
|
@bors rollup |
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
…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
…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`)
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
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
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
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
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 build 67ecc0e |
This comment has been minimized.
This comment has been minimized.
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
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
|
Finished benchmarking commit (67ecc0e): comparison URL. Overall result: ❌✅ regressions and improvements - please read the text belowBenchmarking 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 @bors rollup=never Instruction countOur most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.
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.
CyclesResults (secondary -0.7%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Binary sizeThis benchmark run did not return any relevant results for this metric. Bootstrap: 475.191s -> 477.005s (0.38%) |
|
Sadly perf is a bit more negative than it was before. |
Pkgsrc changes: * Update version & checksums, and adapt to new libc crate included. Upstream changes relative to 1.94.1: Version 1.95 (2026-04-16) ========================== Language -------- - [Stabilize `if let` guards on match arms] (rust-lang/rust#141295) - [`irrefutable_let_patterns` lint no longer lints on let chains] (rust-lang/rust#146832) - [Support importing path-segment keywords with renaming] (rust-lang/rust#146972) - [Stabilize inline assembly for PowerPC and PowerPC64] (rust-lang/rust#147996) - [const-eval: be more consistent in the behavior of padding during typed copies] (rust-lang/rust#148967) - [Const blocks are no longer evaluated to determine if expressions involving fallible operations can implicitly be constant-promoted.] (rust-lang/rust#150557). Expressions whose ability to implicitly be promoted would depend on the result of a const block are no longer implicitly promoted. - [Make operational semantics of pattern matching independent of crate and module] (rust-lang/rust#150681) Compiler -------- - [Stabilize `--remap-path-scope` for controlling the scoping of how paths get remapped in the resulting binary] (rust-lang/rust#147611) Platform Support ---------------- - [Promote `powerpc64-unknown-linux-musl` to Tier 2 with host tools] (rust-lang/rust#149962) - [Promote `aarch64-apple-tvos` to Tier 2] (rust-lang/rust#152021) - [Promote `aarch64-apple-tvos-sim` to Tier 2] (rust-lang/rust#152021) - [Promote `aarch64-apple-watchos` to Tier 2] (rust-lang/rust#152021) - [Promote `aarch64-apple-watchos-sim` to Tier 2] (rust-lang/rust#152021) - [Promote `aarch64-apple-visionos` to Tier 2] (rust-lang/rust#152021) - [Promote `aarch64-apple-visionos-sim` to Tier 2] (rust-lang/rust#152021) Refer to Rust's [platform support page][platform-support-doc] for more information on Rust's tiered platform support. https://doc.rust-lang.org/rustc/platform-support.html Libraries --------- - [`thread::scope`: document how join interacts with TLS destructors] (rust-lang/rust#149482) - [Speed up `str::contains` on aarch64 targets with `neon` target feature enabled by default] (rust-lang/rust#152176) Stabilized APIs --------------- - [`MaybeUninit<[T; N]>: From<[MaybeUninit<T>; N]>`] (https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#impl-From%3CMaybeUninit%3C%5BT;+N%5D%3E%3E-for-%5BMaybeUninit%3CT%3E;+N%5D) - [`MaybeUninit<[T; N]>: AsRef<[MaybeUninit<T>; N]>`] (https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#impl-AsRef%3C%5BMaybeUninit%3CT%3E;+N%5D%3E-for-MaybeUninit%3C%5BT;+N%5D%3E) - [`MaybeUninit<[T; N]>: AsRef<[MaybeUninit<T>]>`] (https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#impl-AsRef%3C%5BMaybeUninit%3CT%3E%5D%3E-for-MaybeUninit%3C%5BT;+N%5D%3E) - [`MaybeUninit<[T; N]>: AsMut<[MaybeUninit<T>; N]>`] (https://doc.rust-lang.org/beta/std/mem/union.MaybeUninit.html#impl-AsMut%3C%5BMaybeUninit%3CT%3E;+N%5D%3E-for-MaybeUninit%3C%5BT;+N%5D%3E) - [`MaybeUninit<[T; N]>: AsMut<[MaybeUninit<T>]>`] (https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#impl-AsMut%3C%5BMaybeUninit%3CT%3E%5D%3E-for-MaybeUninit%3C%5BT;+N%5D%3E) - [`[MaybeUninit<T>; N]: From<MaybeUninit<[T; N]>>`] (https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#impl-From%3C%5BMaybeUninit%3CT%3E;+N%5D%3E-for-MaybeUninit%3C%5BT;+N%5D%3E) - [`Cell<[T; N]>: AsRef<[Cell<T>; N]>`] (https://doc.rust-lang.org/stable/std/cell/struct.Cell.html#impl-AsRef%3C%5BCell%3CT%3E;+N%5D%3E-for-Cell%3C%5BT;+N%5D%3E) - [`Cell<[T; N]>: AsRef<[Cell<T>]>`] (https://doc.rust-lang.org/stable/std/cell/struct.Cell.html#impl-AsRef%3C%5BCell%3CT%3E%5D%3E-for-Cell%3C%5BT;+N%5D%3E) - [`Cell<[T]>: AsRef<[Cell<T>]>`] (https://doc.rust-lang.org/stable/std/cell/struct.Cell.html#impl-AsRef%3C%5BCell%3CT%3E%5D%3E-for-Cell%3C%5BT%5D%3E) - [`bool: TryFrom<{integer}>`] (https://doc.rust-lang.org/stable/std/primitive.bool.html#impl-TryFrom%3Cu128%3E-for-bool) - [`AtomicPtr::update`] (https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicPtr.html#method.update) - [`AtomicPtr::try_update`] (https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicPtr.html#method.try_update) - [`AtomicBool::update`] (https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicBool.html#method.update) - [`AtomicBool::try_update`] (https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicBool.html#method.try_update) - [`AtomicIn::update`] (https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicIsize.html#method.update) - [`AtomicIn::try_update`] (https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicIsize.html#method.try_update) - [`AtomicUn::update`] (https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicUsize.html#method.update) - [`AtomicUn::try_update`] (https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicUsize.html#method.try_update) - [`cfg_select!`] (https://doc.rust-lang.org/stable/std/macro.cfg_select.html) - [`mod core::range`] (https://doc.rust-lang.org/stable/core/range/index.html) - [`core::range::RangeInclusive`] (https://doc.rust-lang.org/stable/core/range/struct.RangeInclusive.html) - [`core::range::RangeInclusiveIter`] (https://doc.rust-lang.org/stable/core/range/struct.RangeInclusiveIter.html) - [`core::hint::cold_path`] (https://doc.rust-lang.org/stable/core/hint/fn.cold_path.html) - [`<*const T>::as_ref_unchecked`] (https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.as_ref_unchecked) - [`<*mut T>::as_ref_unchecked`] (https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.as_ref_unchecked-1) - [`<*mut T>::as_mut_unchecked`] (https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.as_mut_unchecked) These previously stable APIs are now stable in const contexts: - [`fmt::from_fn`] (https://doc.rust-lang.org/stable/std/fmt/fn.from_fn.html) - [`ControlFlow::is_break`] (https://doc.rust-lang.org/stable/core/ops/enum.ControlFlow.html#method.is_break) - [`ControlFlow::is_continue`] (https://doc.rust-lang.org/stable/core/ops/enum.ControlFlow.html#method.is_continue) Cargo ----- - [docs(report): enhance man pages for `cargo report *`] (rust-lang/cargo#16430) Rustdoc ----- - [In search results, rank unstable items lower] (rust-lang/rust#149460) - [Add new "hide deprecated items" setting in rustdoc] (rust-lang/rust#151091) Compatibility Notes ------------------- - [Array coercions may now result in less inference constraints than before] (rust-lang/rust#140283) - Importing `$crate` without renaming, i.e. `use $crate::{self};`, is now no longer permitted due to stricter error checking for `self` imports. - [const-eval: be more consistent in the behavior of padding during typed copies.] (rust-lang/rust#148967) In very rare cases, this may cause compilation errors due to bytes from parts of a pointer ending up in the padding bytes of a `const` or `static`. - [A future-incompatibility warning lint `ambiguous_glob_imported_traits` is now reported when using an ambiguously glob imported trait] (rust-lang/rust#149058) - [Check lifetime bounds of types mentioning only type parameters] (rust-lang/rust#149389) - [Report more visibility-related ambiguous import errors] (rust-lang/rust#149596) - [Deprecate `Eq::assert_receiver_is_total_eq` and emit future compatibility warnings on manual impls] (rust-lang/rust#149978) - [powerpc64: Use the ELF ABI version set in target spec instead of guessing] (rust-lang/rust#150468) (fixes the ELF ABI used by the OpenBSD target) - Matching on a `#[non_exhaustive]` enum [now reads the discriminant, even if the enum has only one variant] (rust-lang/rust#150681). This can cause closures to capture values that they previously wouldn't. - `mut ref` and `mut ref mut` patterns, part of the unstable [Match Ergonomics 2024 RFC] (rust-lang/rust#123076), were accidentally allowed on stable within struct pattern field shorthand. These patterns are now correctly feature-gated as unstable in this position. - [Add future-compatibility warning for derive helper attributes which conflict with built-in attributes] (rust-lang/rust#151152) - [JSON target specs] (https://doc.rust-lang.org/rustc/targets/custom.html) have been destabilized and now require `-Z unstable-options` to use. Previously, they could not be used without the standard library, which has no stable build mechanism. In preparation for the `build-std` project adding that support, JSON target specs are being proactively gated to ensure they remain unstable even if `build-std` is stabilized. Cargo now includes the `-Z json-target-spec` CLI flag to automatically pass `-Z unstable-options` to the compiler when needed. See [#150151] (rust-lang/rust#150151), [#151534] (rust-lang/rust#150151), and [rust-lang/cargo#16557] (rust-lang/cargo#16557). - [The arguments of `#[feature]` attributes on invalid targets are now checked] (rust-lang/rust#153764) Internal Changes ---------------- These changes do not affect any public interfaces of Rust, but they represent significant improvements to the performance or internals of rustc and related tools. - [Update to LLVM 22](rust-lang/rust#150722)
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [rust](https://github.com/rust-lang/rust) | | minor | `1.94.0` → `1.95.0` | | rust | stage | minor | `1.94-bookworm` → `1.95-bookworm` | --- ### Release Notes <details> <summary>rust-lang/rust (rust)</summary> ### [`v1.95.0`](https://github.com/rust-lang/rust/blob/HEAD/RELEASES.md#Version-1950-2026-04-16) [Compare Source](rust-lang/rust@1.94.1...1.95.0) \=========================== <a id="1.95-Language"></a> ## Language - [Stabilize `if let` guards on match arms](rust-lang/rust#141295) - [`irrefutable_let_patterns` lint no longer lints on let chains](rust-lang/rust#146832) - [Support importing path-segment keywords with renaming](rust-lang/rust#146972) - [Stabilize inline assembly for PowerPC and PowerPC64](rust-lang/rust#147996) - [const-eval: be more consistent in the behavior of padding during typed copies](rust-lang/rust#148967) - [Const blocks are no longer evaluated to determine if expressions involving fallible operations can implicitly be constant-promoted.](rust-lang/rust#150557). Expressions whose ability to implicitly be promoted would depend on the result of a const block are no longer implicitly promoted. - [Make operational semantics of pattern matching independent of crate and module](rust-lang/rust#150681) <a id="1.95-Compiler"></a> ## Compiler - [Stabilize `--remap-path-scope` for controlling the scoping of how paths get remapped in the resulting binary](rust-lang/rust#147611) - [Apply patches for CVE-2026-6042 and CVE-2026-40200 to vendored musl](rust-lang/rust#155171) <a id="1.95-Platform-Support"></a> ## Platform Support - [Promote `powerpc64-unknown-linux-musl` to Tier 2 with host tools](rust-lang/rust#149962) - [Promote `aarch64-apple-tvos` to Tier 2](rust-lang/rust#152021) - [Promote `aarch64-apple-tvos-sim` to Tier 2](rust-lang/rust#152021) - [Promote `aarch64-apple-watchos` to Tier 2](rust-lang/rust#152021) - [Promote `aarch64-apple-watchos-sim` to Tier 2](rust-lang/rust#152021) - [Promote `aarch64-apple-visionos` to Tier 2](rust-lang/rust#152021) - [Promote `aarch64-apple-visionos-sim` to Tier 2](rust-lang/rust#152021) Refer to Rust's [platform support page][platform-support-doc] for more information on Rust's tiered platform support. [platform-support-doc]: https://doc.rust-lang.org/rustc/platform-support.html <a id="1.95-Libraries"></a> ## Libraries - [`thread::scope`: document how join interacts with TLS destructors](rust-lang/rust#149482) - [Speed up `str::contains` on aarch64 targets with `neon` target feature enabled by default](rust-lang/rust#152176) <a id="1.95-Stabilized-APIs"></a> ## Stabilized APIs - [`MaybeUninit<[T; N]>: From<[MaybeUninit<T>; N]>`](https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#impl-From%3CMaybeUninit%3C%5BT;+N%5D%3E%3E-for-%5BMaybeUninit%3CT%3E;+N%5D) - [`MaybeUninit<[T; N]>: AsRef<[MaybeUninit<T>; N]>`](https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#impl-AsRef%3C%5BMaybeUninit%3CT%3E;+N%5D%3E-for-MaybeUninit%3C%5BT;+N%5D%3E) - [`MaybeUninit<[T; N]>: AsRef<[MaybeUninit<T>]>`](https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#impl-AsRef%3C%5BMaybeUninit%3CT%3E%5D%3E-for-MaybeUninit%3C%5BT;+N%5D%3E) - [`MaybeUninit<[T; N]>: AsMut<[MaybeUninit<T>; N]>`](https://doc.rust-lang.org/beta/std/mem/union.MaybeUninit.html#impl-AsMut%3C%5BMaybeUninit%3CT%3E;+N%5D%3E-for-MaybeUninit%3C%5BT;+N%5D%3E) - [`MaybeUninit<[T; N]>: AsMut<[MaybeUninit<T>]>`](https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#impl-AsMut%3C%5BMaybeUninit%3CT%3E%5D%3E-for-MaybeUninit%3C%5BT;+N%5D%3E) - [`[MaybeUninit<T>; N]: From<MaybeUninit<[T; N]>>`](https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#impl-From%3C%5BMaybeUninit%3CT%3E;+N%5D%3E-for-MaybeUninit%3C%5BT;+N%5D%3E) - [`Cell<[T; N]>: AsRef<[Cell<T>; N]>`](https://doc.rust-lang.org/stable/std/cell/struct.Cell.html#impl-AsRef%3C%5BCell%3CT%3E;+N%5D%3E-for-Cell%3C%5BT;+N%5D%3E) - [`Cell<[T; N]>: AsRef<[Cell<T>]>`](https://doc.rust-lang.org/stable/std/cell/struct.Cell.html#impl-AsRef%3C%5BCell%3CT%3E%5D%3E-for-Cell%3C%5BT;+N%5D%3E) - [`Cell<[T]>: AsRef<[Cell<T>]>`](https://doc.rust-lang.org/stable/std/cell/struct.Cell.html#impl-AsRef%3C%5BCell%3CT%3E%5D%3E-for-Cell%3C%5BT%5D%3E) - [`bool: TryFrom<{integer}>`](https://doc.rust-lang.org/stable/std/primitive.bool.html#impl-TryFrom%3Cu128%3E-for-bool) - [`AtomicPtr::update`](https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicPtr.html#method.update) - [`AtomicPtr::try_update`](https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicPtr.html#method.try_update) - [`AtomicBool::update`](https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicBool.html#method.update) - [`AtomicBool::try_update`](https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicBool.html#method.try_update) - [`AtomicIn::update`](https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicIsize.html#method.update) - [`AtomicIn::try_update`](https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicIsize.html#method.try_update) - [`AtomicUn::update`](https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicUsize.html#method.update) - [`AtomicUn::try_update`](https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicUsize.html#method.try_update) - [`cfg_select!`](https://doc.rust-lang.org/stable/std/macro.cfg_select.html) - [`mod core::range`](https://doc.rust-lang.org/stable/core/range/index.html) - [`core::range::RangeInclusive`](https://doc.rust-lang.org/stable/core/range/struct.RangeInclusive.html) - [`core::range::RangeInclusiveIter`](https://doc.rust-lang.org/stable/core/range/struct.RangeInclusiveIter.html) - [`core::hint::cold_path`](https://doc.rust-lang.org/stable/core/hint/fn.cold_path.html) - [`<*const T>::as_ref_unchecked`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.as_ref_unchecked) - [`<*mut T>::as_ref_unchecked`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.as_ref_unchecked-1) - [`<*mut T>::as_mut_unchecked`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.as_mut_unchecked) - [`Vec::push_mut`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.push_mut) - [`Vec::insert_mut`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.insert_mut) - [`VecDeque::push_front_mut`](https://doc.rust-lang.org/stable/std/collections/struct.VecDeque.html#method.push_front_mut) - [`VecDeque::push_back_mut`](https://doc.rust-lang.org/stable/std/collections/struct.VecDeque.html#method.push_back_mut) - [`VecDeque::insert_mut`](https://doc.rust-lang.org/stable/std/collections/struct.VecDeque.html#method.insert_mut) - [`LinkedList::push_front_mut`](https://doc.rust-lang.org/stable/std/collections/struct.LinkedList.html#method.push_front_mut) - [`LinkedList::push_back_mut`](https://doc.rust-lang.org/stable/std/collections/struct.LinkedList.html#method.push_back_mut) - [`Layout::dangling_ptr`](https://doc.rust-lang.org/stable/std/alloc/struct.Layout.html#method.dangling_ptr) - [`Layout::repeat`](https://doc.rust-lang.org/stable/std/alloc/struct.Layout.html#method.repeat) - [`Layout::repeat_packed`](https://doc.rust-lang.org/stable/std/alloc/struct.Layout.html#method.repeat_packed) - [`Layout::extend_packed`](https://doc.rust-lang.org/stable/std/alloc/struct.Layout.html#method.extend_packed) These previously stable APIs are now stable in const contexts: - [`fmt::from_fn`](https://doc.rust-lang.org/stable/std/fmt/fn.from_fn.html) - [`ControlFlow::is_break`](https://doc.rust-lang.org/stable/core/ops/enum.ControlFlow.html#method.is_break) - [`ControlFlow::is_continue`](https://doc.rust-lang.org/stable/core/ops/enum.ControlFlow.html#method.is_continue) <a id="1.95-Rustdoc"></a> ## Rustdoc - [In search results, rank unstable items lower](rust-lang/rust#149460) - [Add new "hide deprecated items" setting in rustdoc](rust-lang/rust#151091) <a id="1.95-Compatibility-Notes"></a> ## Compatibility Notes - [Array coercions may now result in less inference constraints than before](rust-lang/rust#140283) - Importing `$crate` without renaming, i.e. `use $crate::{self};`, is now no longer permitted due to stricter error checking for `self` imports. - [const-eval: be more consistent in the behavior of padding during typed copies.](rust-lang/rust#148967) In very rare cases, this may cause compilation errors due to bytes from parts of a pointer ending up in the padding bytes of a `const` or `static`. - [A future-incompatibility warning lint `ambiguous_glob_imported_traits` is now reported when using an ambiguously glob imported trait](rust-lang/rust#149058) - [Check lifetime bounds of types mentioning only type parameters](rust-lang/rust#149389) - [Report more visibility-related ambiguous import errors](rust-lang/rust#149596) - [Deprecate `Eq::assert_receiver_is_total_eq` and emit future compatibility warnings on manual impls](rust-lang/rust#149978) - [powerpc64: Use the ELF ABI version set in target spec instead of guessing](rust-lang/rust#150468) (fixes the ELF ABI used by the OpenBSD target) - Matching on a `#[non_exhaustive]` enum [now reads the discriminant, even if the enum has only one variant](rust-lang/rust#150681). This can cause closures to capture values that they previously wouldn't. - `mut ref` and `mut ref mut` patterns, part of the unstable [Match Ergonomics 2024 RFC](rust-lang/rust#123076), were accidentally allowed on stable within struct pattern field shorthand. These patterns are now correctly feature-gated as unstable in this position. - [Add future-compatibility warning for derive helper attributes which conflict with built-in attributes](rust-lang/rust#151152) - [JSON target specs](https://doc.rust-lang.org/rustc/targets/custom.html) have been destabilized and now require `-Z unstable-options` to use. Previously, they could not be used without the standard library, which has no stable build mechanism. In preparation for the `build-std` project adding that support, JSON target specs are being proactively gated to ensure they remain unstable even if `build-std` is stabilized. Cargo now includes the `-Z json-target-spec` CLI flag to automatically pass `-Z unstable-options` to the compiler when needed. See [#​150151](rust-lang/rust#150151), [#​151534](rust-lang/rust#150151), and [rust-lang/cargo#16557](rust-lang/cargo#16557). - [The arguments of `#[feature]` attributes on invalid targets are now checked](rust-lang/rust#153764) <a id="1.95-Internal-Changes"></a> ## Internal Changes These changes do not affect any public interfaces of Rust, but they represent significant improvements to the performance or internals of rustc and related tools. - [Update to LLVM 22](rust-lang/rust#150722) ### [`v1.94.1`](https://github.com/rust-lang/rust/blob/HEAD/RELEASES.md#Version-1941-2026-03-26) [Compare Source](rust-lang/rust@1.94.0...1.94.1) \=========================== <a id="1.94.1"></a> - [Fix `std::thread::spawn` on wasm32-wasip1-threads](rust-lang/rust#153634) - [Remove new methods added to `std::os::windows::fs::OpenOptionsExt`](rust-lang/rust#153491) The new methods were unstable, but the trait itself is not sealed and so cannot be extended with non-default methods. - [Clippy: fix ICE in `match_same_arms`](rust-lang/rust-clippy#16685) - [Cargo: update tar to 0.4.45](rust-lang/cargo#16769) This resolves CVE-2026-33055 and CVE-2026-33056. Users of crates.io are not affected. See [blog](https://blog.rust-lang.org/2026/03/21/cve-2026-33056/) for more details. </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xMDEuMSIsInVwZGF0ZWRJblZlciI6IjQzLjEwMS4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJyZW5vdmF0ZS9jb250YWluZXIiLCJ0eXBlL21pbm9yIl19--> Reviewed-on: https://git.erwanleboucher.dev/eleboucher/towonel/pulls/4
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
Originally posted by @RalfJung in #148470
Originally posted by @RalfJung in #148470
Related: