[WIP]: Do not store tag in uninhabited enum variants, or in the single inhabited variant. #145337
+953
−161
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR contains 3 or 4 changes which could probably be split up:
First (first commit): Remove
TmpLayout
fromlayout_of_enum
. 09a3846 from #103693 made LayoutData not be interned inVariants::Multiple::variants
anymore, so there's no need forTmpLayout
. This should have no noticable effect.Second (second commit): Do not make space for the enum tag in uninhabited variants in the tagged enum layout calculation. This optimizes enums where the uninhabited variants are the largest, and reduces their size by up to the size of the tag. e.g.
enum Foo { A, B(i32, !) }
was 8 bytesA: (tag, uninit), B: (tag, i32, !)
and is now 4 bytesA: (tag,), B: (i32, !)
. Additionally, enums with only zero-sized uninhabited variants are special-cased to return an uninhabited layout of the correct size and alignment without a tag at all, as otherwise we get weird edge cases1Third-ish (seventh commit) (needed for the second and fourth to be sound with
offset_of!
on uninhabited variants' fields): Keep track of the uninhabited variant layouts, even if we use an untagged or uninhabited layout. This is necessary as otherwiseoffset_of!
will "conjure" a layout for uninhabited variants where all fields are at offset 0, which conflicts with partial initialization2.Fourth (ninth commit): Add an additional enum layout that does not encode a tag. This is similar to the existing "single-present-variant" optimization, but works even if some of the uninhabited variants are "present" (have non-1-ZST fields). This works by calculating the layout of the inhabited variant as a struct, and padding it to the maximum size and alignment necessary to fit each uninhabited variant.
The layout changes probably need an MCP and I haven't squashed fully, so draft for now.
r? ghost
Footnotes
Specifically, without the special-case,
enum Foo { A(Aligned2Never), B(Aligned2Never) }
got a size-0 layout with ani16
tag field, which I assume would cause problems. ↩This isn't an issue before this PR because the layout algorithm only produces
Variants::Empty
orVariants::Single
when all uninhabited variants are "absent", i.e. have only 1-ZST fields ↩