Skip to content

Structs with no fields or all-ZST fields are ZSTs#2262

Open
DanielEScherzer wants to merge 2 commits into
rust-lang:masterfrom
DanielEScherzer:zst-structs
Open

Structs with no fields or all-ZST fields are ZSTs#2262
DanielEScherzer wants to merge 2 commits into
rust-lang:masterfrom
DanielEScherzer:zst-structs

Conversation

@DanielEScherzer

@DanielEScherzer DanielEScherzer commented May 5, 2026

Copy link
Copy Markdown
Contributor

Guarantee that structs with Rust representation and with no fields, or where all fields are ZSTs, are themselves ZSTs.

Guarantee that enums with Rust representation with a single struct-like variant with no fields, or where all fields are ZSTs, are themselves ZSTs.

@rustbot rustbot added the S-waiting-on-review Status: The marked PR is awaiting review from a maintainer label May 5, 2026
@DanielEScherzer DanielEScherzer changed the title New rule: items.struct.zst New rules for ZSTs May 5, 2026
@traviscross traviscross changed the title New rules for ZSTs New rules for structs with no fields May 5, 2026
@traviscross traviscross changed the title New rules for structs with no fields Structs with no fields are ZSTs May 5, 2026
@traviscross traviscross changed the title Structs with no fields are ZSTs Structs with no fields or all-ZST fields are ZSTs May 5, 2026
@traviscross traviscross added I-lang-nominated Nominated for discussion during a lang team meeting. P-lang-drag-1 Lang team prioritization drag level 1. T-lang Relevant to the language team. labels May 5, 2026
@traviscross

Copy link
Copy Markdown
Contributor

cc @RalfJung @rust-lang/opsem

Comment thread src/type-layout.md
For [structs] with no fields, or where all fields are [zero-sized], it is further guaranteed that the structs are themselves [zero-sized].

r[layout.repr.rust.enum-struct-like-zst]
For [enums] (without a primitive representation specified) with a single struct-like variant with no fields or where all fields are [zero-sized], the enum itself is [zero-sized].

@theemathas theemathas May 6, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems bizarre to guarantee this for struct-like variants but not unit-like variants or tuple-like variants.

View changes since the review

@RalfJung

RalfJung commented May 6, 2026

Copy link
Copy Markdown
Member

That seems reasonable to me (specifically for repr(Rust); not necessarily for other reprs). Someone should check whether it is honored by -Zrandomize-layout.

@traviscross

traviscross commented May 6, 2026

Copy link
Copy Markdown
Contributor

We talked about this in the lang call today. Let's propose to do this with the correction that, for enums, we mean those repr(Rust) enums without a primitive representation specified and that have a single field-struct-like variant, a single unit-struct-like variant, or a single tuple-struct-like variant where the struct-like thing has no fields or where all of the fields are zero-sized.

@rfcbot fcp merge lang

@rust-rfcbot

rust-rfcbot commented May 6, 2026

Copy link
Copy Markdown
Collaborator

@traviscross has proposed to merge this. The next step is review by the rest of the tagged team members:

Concerns:

Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

cc @rust-lang/lang-advisors: FCP proposed for lang, please feel free to register concerns.
See this document for info about what commands tagged team members can give me.

@traviscross

Copy link
Copy Markdown
Contributor

@rfcbot concern check-randomize-layout

@tmandry

tmandry commented May 6, 2026

Copy link
Copy Markdown
Member

This seems stronger than what we guarantee for non-ZST structs, which require #[repr(transparent)] to have the same representation as the inner type. In the lang meeting, @steffahn pointed out that the non-ZST case is harder because certain types get passed in registers, etc.

I don't see a reason not to make this guarantee, and it seems like a useful one, so let's do it.

@rfcbot reviewed

@traviscross traviscross added I-lang-radar Items that are on lang's radar and will need eventual work or consideration. and removed I-lang-nominated Nominated for discussion during a lang team meeting. P-lang-drag-1 Lang team prioritization drag level 1. labels May 13, 2026
@zachs18

zachs18 commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Should we also guarantee that zero-variant repr(Rust) enums are ZSTs? They currently are in practice.


Someone should check whether it is honored by -Zrandomize-layout.

Yes, I believe it is. IIUC the current implementation of -Zrandomize-layout only reorderes fields, never introduces any "extra" padding1. Shuffling the field order cannot make a ZST into a non-ZST (or vice versa), so the current implementation upholds the proposed guarantees.

reasoning

When the -Zrandomize-layout flag is enabled, the compiler enables ReprFlags::RANDOMIZE_LAYOUT for types defined in that crate (src) (unstable_opts.randomize_layout is not mentioned anywhere else in the compiler).

ReprFlags::RANDOMIZE_LAYOUT is mentioned in four places in the compiler:

  1. When it is declared (src)
  2. When it is enabled (see previous section)
  3. In SizeSkeleton, which IIUC ignores it when computing the size of generic NPO-optimized enums and newtype structs/enums (src)
    1. NPO is irrelevant here (there are no ZSTs eligible for NPO optimization)
    2. For newtypes over ZSTs, this should correctly give a ZST size regardless of RANDOMIZE_LAYOUT
  4. When it is used in ReprOptions::can_randomize_type_layout which returns !self.inhibit_struct_field_reordering() && self.flags.contains(ReprFlags::RANDOMIZE_LAYOUT) (src)

ReprOptions::can_randomize_type_layout is used in one place in the compiler: in layout computation (fn univariant_biased) where the field list (excluding the unsized tail) is shuffled if it returns true (instead of being optimized by sorting by alignment) (src). Shuffling (or sorting) the field order cannot make a ZST into a non-ZST (or vice versa), so the current implementation upholds the proposed guarantees.

I opened a PR rust-lang/rust#157905 to update the comments in some of the places where -Zrandomize-layout is implemented referring back to this FCP to ensure that future changes to -Zrandomize-layout do not break these guarantees.

Footnotes

  1. other than the padding necessary to make fields aligned, and since 0 is a multiple of any alignment, this padding is never added if all fields are zero-sized

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

disposition-merge I-lang-radar Items that are on lang's radar and will need eventual work or consideration. proposed-final-comment-period S-waiting-on-review Status: The marked PR is awaiting review from a maintainer T-lang Relevant to the language team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants