Skip to content
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

Document field struct alignment guarantees? #1151

Closed
dureuill opened this issue Jan 30, 2022 · 4 comments · Fixed by #1152
Closed

Document field struct alignment guarantees? #1151

dureuill opened this issue Jan 30, 2022 · 4 comments · Fixed by #1152
Labels
A-type-layout Area: type layout

Comments

@dureuill
Copy link

This recently posted article makes that point that, because the default representation makes no guarantees of data layout, one must use write_unaligned to write to the fields of a struct when initializing it field by field.

This runs contrary to the the documentation of MaybeUninit about initializing a struct field by field, and also to what the nomicon has to say on the subject:

By default, composite structures have an alignment equal to the maximum of their fields' alignments. Rust will consequently insert padding where necessary to ensure that all fields are properly aligned and that the overall type's size is a multiple of its alignment.

Should we amend the reference to either link to the nomicon for more details, or to specify that fields that can be accessed in a struct are properly aligned (no write_unaligned necessary)?

@dureuill
Copy link
Author

I'd propose a formulation, but I'm unsure about e.g. stuff like ZST...

I'd add:

Nominal types without a repr attribute have the default representation. Informally, this representation is also called the rust representation.

Accessible fields of a struct or enum in the default representation are guaranteed to be properly aligned.

There are no other guarantees of data layout made by this representation.

What do you think?

@Gankra
Copy link
Contributor

Gankra commented Jan 30, 2022

I don't know the precise wording the reference likes, but yes repr(rust) must align all of its fields.

Zero-sized-types must also be completely aligned. Most have align 1 so they are trivially always aligned. The major exception is [T; 0] which is size 0 but aligned to T. In the times before Rust had proper alignment attributes, this was relied upon to specify a struct needed more alignment than the other fields suggested.

There is otherwise no burden for keeping ZSTs aligned in repr(rust) because the compiler is always free to logically reorder them to the start of the struct which has maximum alignment. Because they have no size, they do not "waste" that alignment and the non-ZST fields can still start at offset 0.

@ehuss ehuss added the A-type-layout Area: type layout label Jan 30, 2022
@RalfJung
Copy link
Member

RalfJung commented Jan 30, 2022

because the default representation makes no guarantees of data layout, one must use write_unaligned to write to the fields of a struct when initializing it field by field.

Ah, that is interpreting "no guarantees" way too far. But I agree it is probably worth being more explicit here.

Some things are definitely guaranteed:

  • The fields do not overlap.
  • Each field has the alignment that is required by its type.

These guarantees are required for basic soundness, they are so fundamental that presumably the author of the "no guarantee" line could not imagine a violation even being considered. ;)

@Havvy
Copy link
Contributor

Havvy commented Jan 31, 2022

As the author of that line, it's as @RalfJung says, except that I did know those two requirements at the time; I just failed to convey them anywhere at all. Tuple representation has the same problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-type-layout Area: type layout
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants