transmute: fix check for whether newtypes have equal size - #155418
Conversation
|
r? @JohnTitor rustbot has assigned @JohnTitor. Use Why was this reviewer chosen?The reviewer was selected based on:
|
|
@bors try |
This comment has been minimized.
This comment has been minimized.
transmute: fix check for whether newtypes have equal size
This comment has been minimized.
This comment has been minimized.
|
That's strange, I thought I had fixed this and it worked locally...
|
|
@RalfJung IIRC, the target that failed has Edit: Yup. #t-compiler/help > `Span` is 96 bits? |
|
Ah! There's a "randomize layout" flag. That should not affect crater though so we can go ahead and |
|
👌 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
f5db719 to
9d897cb
Compare
|
Actually, there's another flag we should ignore, and it's set on @craterbot abort |
This comment has been minimized.
This comment has been minimized.
transmute: fix check for whether newtypes have equal size
|
🗑️ Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
9d897cb to
c634619
Compare
|
@rustbot reroll |
|
🔔 This is now entering its final comment period, as per the review above. 🔔 |
|
The final comment period, with a disposition to merge, as per the review above, is now complete. As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed. |
|
@nikomatsakis this is just waiting for review now. :) |
| // We can ignore the seed and some particular flags that can never affect the | ||
| // layout of newtypes / NPO types, but we have to check everything else. | ||
| // If you are adding a new field to `ReprOptions`, make sure to extend the check | ||
| // below so that we bail out if it is not at its default value! |
There was a problem hiding this comment.
I guess it's ok, reading it more closely.
|
@bors r+ |
…uwer Rollup of 6 pull requests Successful merges: - #155418 (transmute: fix check for whether newtypes have equal size) - #156603 (Clarify E0381 diagnostics for branch conditions) - #156643 (Document run-make external dependencies) - #157009 (Avoid `unreachable_code` on required return values) - #157308 (make typing mode exhaustive again...) - #157312 (disallow most attrs on eiis)
…uwer Rollup of 6 pull requests Successful merges: - #155418 (transmute: fix check for whether newtypes have equal size) - #156603 (Clarify E0381 diagnostics for branch conditions) - #156643 (Document run-make external dependencies) - #157009 (Avoid `unreachable_code` on required return values) - #157308 (make typing mode exhaustive again...) - #157312 (disallow most attrs on eiis)
Rollup merge of #155418 - RalfJung:transmute-newtypes, r=nikomatsakis transmute: fix check for whether newtypes have equal size The `transmute` check has some logic to be able to tell whether two types that involve generics will always have the same size. That logic has a bug: it ignores the fact that `repr(align)` can affect the size of a type. This PR fixes that bug by making the check bail out for most `repr` flags. That rejects some previously accepted code, hence the @rust-lang/lang nomination. The new logic says that a type is a transparent newtype wrapper around a pointer for `transmute` purposes only if - It is a struct without any `repr` flags except for `repr(transparent)` and `repr(C)`. - It is a single-variant enum without any `repr` flags except for `repr(transparent)`. - Or it is a two-variant enum without any `repr` flags except for `repr(transparent)` that matches the NPO rules. The inner type must be `non_zero: true` (which holds for references and `NonNull`), and the wrapper type is then marked as `non_zero: false`. Fixes #155412 Fixes #88290 I manually checked that the playground example linked in #88290 now emits all three expected errors (and we have equivalent cases in the tests, either preexisting or added by this PR, so it didn't seem worth adding that example as well).
…uwer Rollup of 6 pull requests Successful merges: - rust-lang/rust#155418 (transmute: fix check for whether newtypes have equal size) - rust-lang/rust#156603 (Clarify E0381 diagnostics for branch conditions) - rust-lang/rust#156643 (Document run-make external dependencies) - rust-lang/rust#157009 (Avoid `unreachable_code` on required return values) - rust-lang/rust#157308 (make typing mode exhaustive again...) - rust-lang/rust#157312 (disallow most attrs on eiis)
This MR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [rust](https://github.com/rust-lang/rust) | tools | minor | `1.97.1` → `1.98.0` | MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot). **Proposed changes to behavior should be submitted there as MRs.** --- ### Release Notes <details> <summary>rust-lang/rust (rust)</summary> ### [`v1.98.0`](https://github.com/rust-lang/rust/blob/HEAD/RELEASES.md#Version-1980-2026-08-20) [Compare Source](rust-lang/rust@1.97.1...1.98.0) \========================== <a id="1.98.0-Language"></a> ## Language - [Allow shortening lifetime of `&mut` when unsize-coercing, even in an invariant position.](rust-lang/rust#149219) For example, you can now coerce a `Cell<&'long mut i32>` to a `Cell<&'short mut dyn Send>`. Such shortenings were already previously allowed when coercing a `&mut` to a `&`, or coercing a `&` to a `&`. - [Add deny-by-default `invalid_runtime_symbol_definitions` lint and warn-by-default `suspicious_runtime_symbol_definitions` lint](rust-lang/rust#155521) - The lints currently specifically targets `core` runtime symbols like `memcmp`, `memset`, `strlen`, ... and is planned to be expanded in the next few releases. - [Add warn-by-default `c_void_returns` lint to check `core::ffi::c_void` as a return type](rust-lang/rust#156379) <a id="1.98.0-Platform-Support"></a> ## Platform Support - [Add `powerpc64-unknown-linux-gnuelfv2` as Tier 3](rust-lang/rust#144220) - [Add `aarch64-unknown-linux-pauthtest` as Tier 3 target](rust-lang/rust#155722) - [Promote `thumbv7a-none-eabi` to Tier 2](rust-lang/rust#155763) - [Promote `thumbv7a-none-eabihf` to Tier 2](rust-lang/rust#155763) - [Promote `thumbv7r-none-eabi` to Tier 2](rust-lang/rust#155763) - [Promote `thumbv7r-none-eabihf` to Tier 2](rust-lang/rust#155763) - [Promote `thumbv8r-none-eabihf` to Tier 2](rust-lang/rust#155763) 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.98.0-Libraries"></a> ## Libraries - [Change `Location<'_>` lifetime to `'static` in `Panic[Hook]Info`](rust-lang/rust#146561) - [Document panic in `RangeInclusive::from(legacy::RangeInclusive)`](rust-lang/rust#155421) - [Document that `ManuallyDrop`'s `Box` interaction has been fixed](rust-lang/rust#155750) - [Stabilize LoongArch CRC Intrinsics](rust-lang/rust#156908) - [The `derive` macro is available at `{core,std}::derive`.](rust-lang/rust#154645) This was previously [unintentionally stabilized in 1.96](rust-lang/rust#159856), but is now [explicitly accepted](rust-lang/rust#154645) as a stabilized API. - Please note that the MSRV for `{core,std}::derive` will be 1.96, and not 1.98. <a id="1.98.0-Stabilized-APIs"></a> ## Stabilized APIs - [`str::substr_range`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.substr_range) - [`[T]::subslice_range`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.subslice_range) - [`core::fmt::NumBuffer`](https://doc.rust-lang.org/stable/core/fmt/struct.NumBuffer.html) - [`<{integer}>::format_into`](https://doc.rust-lang.org/stable/core/primitive.usize.html#method.format_into) - [`Send/Sync for std::process::CommandArgs`](https://doc.rust-lang.org/stable/std/process/struct.CommandArgs.html#impl-Send-for-CommandArgs%3C'a%3E) - [`{fN}::algebraic_add`](https://doc.rust-lang.org/stable/core/primitive.f32.html#method.algebraic_add) - [`{fN}::algebraic_sub`](https://doc.rust-lang.org/stable/core/primitive.f32.html#method.algebraic_sub) - [`{fN}::algebraic_mul`](https://doc.rust-lang.org/stable/core/primitive.f32.html#method.algebraic_mul) - [`{fN}::algebraic_div`](https://doc.rust-lang.org/stable/core/primitive.f32.html#method.algebraic_div) - [`{fN}::algebraic_rem`](https://doc.rust-lang.org/stable/core/primitive.f32.html#method.algebraic_rem) - [`NonZero<{integer}>::from_str_radix`](https://doc.rust-lang.org/stable/core/num/struct.NonZero.html#method.from_str_radix-4) - [`String::from_utf16le`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.from_utf16le) - [`String::from_utf16le_lossy`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.from_utf16le_lossy) - [`String::from_utf16be`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.from_utf16be) - [`String::from_utf16be_lossy`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.from_utf16be_lossy) - [`[T]::strip_circumfix`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.strip_circumfix) - [`str::strip_circumfix`](https://doc.rust-lang.org/stable/core/primitive.str.html#method.strip_circumfix) - [`Atomic<T>::from_mut`](https://doc.rust-lang.org/stable/core/sync/atomic/struct.Atomic.html#method.from_mut) - [`Atomic<T>::get_mut_slice`](https://doc.rust-lang.org/stable/core/sync/atomic/struct.Atomic.html#method.get_mut_slice) - [`Atomic<T>::from_mut_slice`](https://doc.rust-lang.org/stable/core/sync/atomic/struct.Atomic.html#method.from_mut_slice) - [`std::range::legacy`](https://doc.rust-lang.org/stable/std/range/legacy/index.html) <a id="1.98.0-Compatibility-Notes"></a> ## Compatibility Notes - [If fully elided, lifetime bounds of trait object types may now resolve differently or even get rejected in very specific niche scenarios](rust-lang/rust#129543) - [Error in more cases of ambiguous imports](rust-lang/rust#145108) - [Switch the destructors implementation for thread locals on Windows to use Fiber Local Storage (FLS)](rust-lang/rust#148799) - [Convert some cases of the `ambiguous_glob_imports` lint into a hard error](rust-lang/rust#149195) - [Where-bounds of the form `Type = Type` and `Type == Type` are no longer syntactically allowed](rust-lang/rust#153513) - [Ensure Send/Sync is not implemented for std::env::Vars{,Os}](rust-lang/rust#155153) - [Fix that in some attributes, arguments were not properly rejected](rust-lang/rust#155193) - [`repr(transparent)` is now more strict about which fields have "trivial" layout and hence can be ignored: `repr(C)` types, types with private fields, and `#[non_exhaustive]` types are no longer considered "trivial"](rust-lang/rust#155299) - [Correctly check whether types have equal size in `transmute()` when some `repr` attributes are involved.](rust-lang/rust#155418) - [More characters are escaped when printing strings and chars](rust-lang/rust#155527) - [Implement fast path for `derive(PartialOrd)` when deriving `Ord`](rust-lang/rust#155598) This can break crates in practice where a type's PartialOrd and Ord impls were inconsistent with each other. - [Add temporary scope to `assert_eq` and `assert_ne`](rust-lang/rust#155739) - Closed a hole in the pattern matching [structural equality](https://doc.rust-lang.org/reference/patterns.html#constant-patterns) check, preventing cases where a match of a constant would be allowed, despite disagreeing with a manually written `PartialEq` implementation, when a `derive(PartialEq)` implementation for that type also exists. - [On Emscripten the WASM exception handling ABI is now unconditionally used](rust-lang/rust#156928) The `-Zemscripten-wasm-eh=false` flag to switch back to JS exceptions has been removed. - [The UNSAFE\_CODE lint is now consistently emitted for all unsafe attributes](rust-lang/rust#157201) - [Solaris: remove `File::lock` implementation, it has the wrong semantics (return "unsupported" instead)](rust-lang/rust#157509) - [Windows-gnu targets now specify baseline tools versions](rust-lang/rust#158020) - [rustfmt now discovers module files that are defined in `cfg_select!`](rust-lang/rust#158372) This may cause more code to be formatted which was previously ignored. </details> --- ### Configuration 📅 **Schedule**: (UTC) - 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 MR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this MR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box --- This MR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yODguMCIsInVwZGF0ZWRJblZlciI6IjQzLjI4OC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJSZW5vdmF0ZSBCb3QiLCJhdXRvbWF0aW9uOmJvdC1hdXRob3JlZCIsImRlcGVuZGVuY3ktdHlwZTo6bWlub3IiXX0=-->
View all comments
The
transmutecheck has some logic to be able to tell whether two types that involve generics will always have the same size. That logic has a bug: it ignores the fact thatrepr(align)can affect the size of a type. This PR fixes that bug by making the check bail out for mostreprflags. That rejects some previously accepted code, hence the @rust-lang/lang nomination.The new logic says that a type is a transparent newtype wrapper around a pointer for
transmutepurposes only ifreprflags except forrepr(transparent)andrepr(C).reprflags except forrepr(transparent).reprflags except forrepr(transparent)that matches the NPO rules. The inner type must benon_zero: true(which holds for references andNonNull), and the wrapper type is then marked asnon_zero: false.Fixes #155412
Fixes #88290
I manually checked that the playground example linked in #88290 now emits all three expected errors (and we have equivalent cases in the tests, either preexisting or added by this PR, so it didn't seem worth adding that example as well).