-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
safe transmute: support non-ZST, variantful, uninhabited enums #126493
Conversation
Some changes occurred to the CTFE / Miri engine cc @rust-lang/miri |
abi::Variants::Single { .. } => { | ||
// The tag of a `Single` enum is like the tag of the niched | ||
// variant: there's no tag as the discriminant is encoded | ||
// entirely implicitly. If `write_discriminant` ever hits this | ||
// case, we do a "validation read" to ensure the the right | ||
// discriminant is encoded implicitly, so any attempt to write | ||
// the wrong discriminant for a `Single` enum will reliably | ||
// result in UB. | ||
Ok(None) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Requested by @RalfJung here: #126358 (comment)
What about enums like |
I've amended this PR to add a test case for such enums. Those enums are supported, as before; they're covered by the rust/compiler/rustc_transmute/src/layout/tree.rs Lines 363 to 380 in 4a39faa
They don't require any special handling, because they don't get the rust/compiler/rustc_abi/src/layout.rs Lines 195 to 197 in f8e5660
|
So in which case do they fall from the PR description?
|
Whoops, that needs to be updated. |
Btw I am getting a notification from github for each time you push a commit that has |
34f8d2f
to
18f9d5e
Compare
Yikes! Sorry. Done! |
Ah okay. :) |
Agreed. I've updated the PR description and commit message to note the correspondence to |
Previously, `Tree::from_enum`'s implementation branched into three disjoint cases: 1. enums that uninhabited 2. enums for which all but one variant is uninhabited 3. enums with multiple inhabited variants This branching (incorrectly) did not differentiate between variantful and variantless uninhabited enums. In both cases, we assumed (and asserted) that uninhabited enums are zero-sized types. This assumption is false for enums like: enum Uninhabited { A(!, u128) } ...which, currently, has the same size as `u128`. This faulty assumption manifested as the ICE reported in rust-lang#126460. In this PR, we revise the first case of `Tree::from_enum` to consider only the narrow category of "enums that are uninhabited ZSTs". These enums, whose layouts are described with `Variants::Single { index }`, are special in their layouts otherwise resemble the `!` type and cannot be descended into like typical enums. This first case captures uninhabited enums like: enum Uninhabited { A(!, !), B(!) } The second case is revised to consider the broader category of "enums that defer their layout to one of their variants"; i.e., enums whose layouts are described with `Variants::Single { index }` and that do have a variant at `index`. This second case captures uninhabited enums that are not ZSTs, like: enum Uninhabited { A(!, u128) } ...which represent their variants with `Variants::Single`. Finally, the third case is revised to cover the broader category of "enums with multiple variants", which captures uninhabited, non-ZST enums like: enum Uninhabited { A(u8, !), B(!, u32) } ...which represent their variants with `Variants::Multiple`. This PR also adds a comment requested by RalfJung in his review of rust-lang#126358 to `compiler/rustc_const_eval/src/interpret/discriminant.rs`. Fixes rust-lang#126460
@bors r+ rollup |
safe transmute: support non-ZST, variantful, uninhabited enums Previously, `Tree::from_enum`'s implementation branched into three disjoint cases: 1. enums that uninhabited 2. enums for which all but one variant is uninhabited 3. enums with multiple variants This branching (incorrectly) did not differentiate between variantful and variantless uninhabited enums. In both cases, we assumed (and asserted) that uninhabited enums are zero-sized types. This assumption is false for enums like: enum Uninhabited { A(!, u128) } ...which, currently, has the same size as `u128`. This faulty assumption manifested as the ICE reported in rust-lang#126460. In this PR, we revise the first case of `Tree::from_enum` to consider only the narrow category of "enums that are uninhabited ZSTs". These enums, whose layouts are described with `Variants::Single { index }`, are special in their layouts otherwise resemble the `!` type and cannot be descended into like typical enums. This first case captures uninhabited enums like: enum Uninhabited { A(!, !), B(!) } The second case is revised to consider the broader category of "enums that defer their layout to one of their variants"; i.e., enums whose layouts are described with `Variants::Single { index }` and that do have a variant at `index`. This second case captures uninhabited enums that are not ZSTs, like: enum Uninhabited { A(!, u128) } ...which represent their variants with `Variants::Single`. Finally, the third case is revised to cover the broader category of "enums with multiple variants", which captures uninhabited enums like: enum Uninhabited { A(u8, !), B(!, u32) } ...which represent their variants with `Variants::Multiple`. This PR also adds a comment requested by `@RalfJung` in his review of rust-lang#126358 to `compiler/rustc_const_eval/src/interpret/discriminant.rs`. Fixes rust-lang#126460 r? `@compiler-errors`
safe transmute: support non-ZST, variantful, uninhabited enums Previously, `Tree::from_enum`'s implementation branched into three disjoint cases: 1. enums that uninhabited 2. enums for which all but one variant is uninhabited 3. enums with multiple variants This branching (incorrectly) did not differentiate between variantful and variantless uninhabited enums. In both cases, we assumed (and asserted) that uninhabited enums are zero-sized types. This assumption is false for enums like: enum Uninhabited { A(!, u128) } ...which, currently, has the same size as `u128`. This faulty assumption manifested as the ICE reported in rust-lang#126460. In this PR, we revise the first case of `Tree::from_enum` to consider only the narrow category of "enums that are uninhabited ZSTs". These enums, whose layouts are described with `Variants::Single { index }`, are special in their layouts otherwise resemble the `!` type and cannot be descended into like typical enums. This first case captures uninhabited enums like: enum Uninhabited { A(!, !), B(!) } The second case is revised to consider the broader category of "enums that defer their layout to one of their variants"; i.e., enums whose layouts are described with `Variants::Single { index }` and that do have a variant at `index`. This second case captures uninhabited enums that are not ZSTs, like: enum Uninhabited { A(!, u128) } ...which represent their variants with `Variants::Single`. Finally, the third case is revised to cover the broader category of "enums with multiple variants", which captures uninhabited enums like: enum Uninhabited { A(u8, !), B(!, u32) } ...which represent their variants with `Variants::Multiple`. This PR also adds a comment requested by ``@RalfJung`` in his review of rust-lang#126358 to `compiler/rustc_const_eval/src/interpret/discriminant.rs`. Fixes rust-lang#126460 r? ``@compiler-errors``
…llaumeGomez Rollup of 9 pull requests Successful merges: - rust-lang#123782 (Test that opaque types can't have themselves as a hidden type with incompatible lifetimes) - rust-lang#124580 (Suggest removing unused tuple fields if they are the last fields) - rust-lang#125852 (improve tip for inaccessible traits) - rust-lang#126422 (Suggest using a standalone doctest for non-local impl defs) - rust-lang#126427 (Rewrite `intrinsic-unreachable`, `sepcomp-cci-copies`, `sepcomp-inlining` and `sepcomp-separate` `run-make` tests to rmake.rs) - rust-lang#126493 (safe transmute: support non-ZST, variantful, uninhabited enums) - rust-lang#126572 (override user defined channel when using precompiled rustc) - rust-lang#126615 (Add `rustc-ice*` to `.gitignore`) - rust-lang#126632 (Replace `move||` with `move ||`) Failed merges: - rust-lang#126558 (hir_typeck: be more conservative in making "note caller chooses ty param" note) r? `@ghost` `@rustbot` modify labels: rollup
safe transmute: support non-ZST, variantful, uninhabited enums Previously, `Tree::from_enum`'s implementation branched into three disjoint cases: 1. enums that uninhabited 2. enums for which all but one variant is uninhabited 3. enums with multiple variants This branching (incorrectly) did not differentiate between variantful and variantless uninhabited enums. In both cases, we assumed (and asserted) that uninhabited enums are zero-sized types. This assumption is false for enums like: enum Uninhabited { A(!, u128) } ...which, currently, has the same size as `u128`. This faulty assumption manifested as the ICE reported in rust-lang#126460. In this PR, we revise the first case of `Tree::from_enum` to consider only the narrow category of "enums that are uninhabited ZSTs". These enums, whose layouts are described with `Variants::Single { index }`, are special in their layouts otherwise resemble the `!` type and cannot be descended into like typical enums. This first case captures uninhabited enums like: enum Uninhabited { A(!, !), B(!) } The second case is revised to consider the broader category of "enums that defer their layout to one of their variants"; i.e., enums whose layouts are described with `Variants::Single { index }` and that do have a variant at `index`. This second case captures uninhabited enums that are not ZSTs, like: enum Uninhabited { A(!, u128) } ...which represent their variants with `Variants::Single`. Finally, the third case is revised to cover the broader category of "enums with multiple variants", which captures uninhabited enums like: enum Uninhabited { A(u8, !), B(!, u32) } ...which represent their variants with `Variants::Multiple`. This PR also adds a comment requested by ```@RalfJung``` in his review of rust-lang#126358 to `compiler/rustc_const_eval/src/interpret/discriminant.rs`. Fixes rust-lang#126460 r? ```@compiler-errors```
Rollup of 10 pull requests Successful merges: - rust-lang#124135 (delegation: Implement glob delegation) - rust-lang#125078 (fix: break inside async closure has incorrect span for enclosing closure) - rust-lang#125293 (Place tail expression behind terminating scope) - rust-lang#126422 (Suggest using a standalone doctest for non-local impl defs) - rust-lang#126493 (safe transmute: support non-ZST, variantful, uninhabited enums) - rust-lang#126504 (Sync fuchsia test runner with clang test runner) - rust-lang#126558 (hir_typeck: be more conservative in making "note caller chooses ty param" note) - rust-lang#126586 (Add `@badboy` and `@BlackHoleFox` as Mac Catalyst maintainers) - rust-lang#126615 (Add `rustc-ice*` to `.gitignore`) - rust-lang#126632 (Replace `move||` with `move ||`) r? `@ghost` `@rustbot` modify labels: rollup
Rollup merge of rust-lang#126493 - jswrenn:fix-126460, r=compiler-errors safe transmute: support non-ZST, variantful, uninhabited enums Previously, `Tree::from_enum`'s implementation branched into three disjoint cases: 1. enums that uninhabited 2. enums for which all but one variant is uninhabited 3. enums with multiple variants This branching (incorrectly) did not differentiate between variantful and variantless uninhabited enums. In both cases, we assumed (and asserted) that uninhabited enums are zero-sized types. This assumption is false for enums like: enum Uninhabited { A(!, u128) } ...which, currently, has the same size as `u128`. This faulty assumption manifested as the ICE reported in rust-lang#126460. In this PR, we revise the first case of `Tree::from_enum` to consider only the narrow category of "enums that are uninhabited ZSTs". These enums, whose layouts are described with `Variants::Single { index }`, are special in their layouts otherwise resemble the `!` type and cannot be descended into like typical enums. This first case captures uninhabited enums like: enum Uninhabited { A(!, !), B(!) } The second case is revised to consider the broader category of "enums that defer their layout to one of their variants"; i.e., enums whose layouts are described with `Variants::Single { index }` and that do have a variant at `index`. This second case captures uninhabited enums that are not ZSTs, like: enum Uninhabited { A(!, u128) } ...which represent their variants with `Variants::Single`. Finally, the third case is revised to cover the broader category of "enums with multiple variants", which captures uninhabited enums like: enum Uninhabited { A(u8, !), B(!, u32) } ...which represent their variants with `Variants::Multiple`. This PR also adds a comment requested by ````@RalfJung```` in his review of rust-lang#126358 to `compiler/rustc_const_eval/src/interpret/discriminant.rs`. Fixes rust-lang#126460 r? ````@compiler-errors````
Previously,
Tree::from_enum
's implementation branched into three disjoint cases:This branching (incorrectly) did not differentiate between variantful and variantless uninhabited enums. In both cases, we assumed (and asserted) that uninhabited enums are zero-sized types. This assumption is false for enums like:
...which, currently, has the same size as
u128
. This faulty assumption manifested as the ICE reported in #126460.In this PR, we revise the first case of
Tree::from_enum
to consider only the narrow category of "enums that are uninhabited ZSTs". These enums, whose layouts are described withVariants::Single { index }
, are special in their layouts otherwise resemble the!
type and cannot be descended into like typical enums. This first case captures uninhabited enums like:The second case is revised to consider the broader category of "enums that defer their layout to one of their variants"; i.e., enums whose layouts are described with
Variants::Single { index }
and that do have a variant atindex
. This second case captures uninhabited enums that are not ZSTs, like:...which represent their variants with
Variants::Single
.Finally, the third case is revised to cover the broader category of "enums with multiple variants", which captures uninhabited enums like:
...which represent their variants with
Variants::Multiple
.This PR also adds a comment requested by @RalfJung in his review of #126358 to
compiler/rustc_const_eval/src/interpret/discriminant.rs
.Fixes #126460
r? @compiler-errors