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

Specify guarantees for repr(rust) structs #1152

Merged

Conversation

Darksonn
Copy link
Contributor

Closes: #1151

Comment on lines +92 to 93
The exception to this is the unit tuple (`()`), which is guaranteed as a
zero-sized type to have a size of 0 and an alignment of 1.
Copy link
Member

Choose a reason for hiding this comment

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

Does the former statement imply this statement?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not as I wrote it here, but you could certainly argue that it should be changed so it does.

Comment on lines 171 to 172
3. The alignment of the struct is not less than the alignment of any of its
fields.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should we guarantee that the alignment is equal to the largest alignment of the fields?

Copy link
Member

Choose a reason for hiding this comment

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

If it ever becomes possible for PGO to change the layout of rust structs, it may be beneficial to increase alignment for certain types in some cases.

Copy link
Contributor

Choose a reason for hiding this comment

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

(Can be ignored by author of PR)

Is it within the scope of the reference to include non-normative statements like:

"In practice, there's no reason a compiler would ever require a type to be more aligned than this, but we would like to reserve the right to do so, in case such a situation is found." (Possibly also noting that there isn't any clear reason why a user would need to care about this unless they were doing something that probably motivates using other repr annotations anyway, so it's basically just erring on the side of compiler freedom in a situation that doesn't much matter either way.).

Copy link
Contributor

Choose a reason for hiding this comment

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

I would avoid saying anything about an upperbound on alignment for repr(Rust), especially if that statement isn't normative, because it might confuse what is guaranteed.

Copy link
Member

Choose a reason for hiding this comment

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

Should we guarantee that the alignment is equal to the largest alignment of the fields?

I would say no. I'd like the freedom to be able to have struct Foo([u8; 16]); automatically get align(4), for example, if not everywhere at least on anything that doesn't like unaligned large reads.

Copy link
Contributor

Choose a reason for hiding this comment

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

Or, for that case, align(16) on x86_64, so you can use aligned SSE reads (movaps) to copy it.

src/type-layout.md Outdated Show resolved Hide resolved
src/type-layout.md Outdated Show resolved Hide resolved
src/type-layout.md Outdated Show resolved Hide resolved
fields can be ordered such that the offset plus the size of any field is less
than or equal to the offset of the next field in the ordering. The ordering does
not have to be the same as the order in which the field are specified in the
declaration of the struct.
Copy link
Contributor

Choose a reason for hiding this comment

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

(also can be ignored)

If non-normative statements that provide motivation/context are permitted, it would also be worth noting here that only the compiler has enough information to optimally lay out a generic type for all possible type substitutions. i.e. repr(C) gets you consistency and control at the cost of sometimes not being able to always put generic fields in the best place.

@dureuill
Copy link

dureuill commented Feb 7, 2022

I'm not sure who is to review this PR, but as the author of #1151, I wanted to make explicit that IMO, merging this PR would completely resolve this issue.

My thanks to the author of the PR.

src/type-layout.md Outdated Show resolved Hide resolved
@ehuss
Copy link
Contributor

ehuss commented Feb 15, 2022

Nominating for t-lang. These seem like reasonable guarantees to add to me, and want to get your input if you agree or have comments.

The only open question I had was would it help to define the layout of struct Foo() to be the same as ().

@joshlf
Copy link
Contributor

joshlf commented Feb 16, 2022

The only open question I had was would it help to define the layout of struct Foo() to be the same as ().

This would be very helpful. E.g., in zerocopy, we want to implement FromBytes for ZSTs like Foo(), but currently aren't convinced that it's sound. If structs like Foo() had the same layout as (), we'd be sure that it is sound.

src/type-layout.md Outdated Show resolved Hide resolved
@joshtriplett
Copy link
Member

@rfcbot merge

@nikomatsakis
Copy link
Contributor

@Darksonn have you seen this write-up here?

https://rust-lang.github.io/unsafe-code-guidelines/layout/structs-and-tuples.html

I didn't do a detailed comparison, but I would like to ensure they are compatible as that text had a fair bit of thought put into it :)

Co-authored-by: Josh Triplett <[email protected]>
@Darksonn
Copy link
Contributor Author

No, I haven't looked at that one in detail either.

@rfcbot
Copy link

rfcbot commented Mar 22, 2022

Team member @joshtriplett 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!

See this document for info about what commands tagged team members can give me.

@@ -86,9 +86,10 @@ String slices are a UTF-8 representation of characters that have the same layout

## Tuple Layout

Tuples do not have any guarantees about their layout.
Tuples have the same layout guarantees as a struct with the same fields when
Copy link
Member

Choose a reason for hiding this comment

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

I'm opposed to documenting this, as it precludes us from tuple variadic approaches which require "tail borrowing."

Copy link
Member

Choose a reason for hiding this comment

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

@rfcbot concern tuple-tail-borrowing

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can you elaborate on what that is?

Copy link
Member

Choose a reason for hiding this comment

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

There have been a number of discussions in relation to variadic generics about wanting the ability to write code which could recurse over the structure of a tuple, HList-style. In order for this to work, the "tail" of a tuple must be represented contiguously. That is, for tuple (A, B, C, D), there must be a sub-tuple (B, C, D) in memory. Allowing arbitrary ordering as structs do would cause layouts like (A, D, C, B), from which it's impossible to create a reference to a tuple of a sub-structure like (B, C, D).

Note that hlist-compatible representations of tuples need not be strictly ordered-- it's fine for each new element to be placed at either the front, back, or even inside of the tuple so long as the tail tuple remains a part of the representation.

I'd like our representation documentation to stay forward-compatible with tuple tail-borrowing until we've explicitly decided not to do it so that users aren't expecting to be able to transmute between struct S(A, B, C, D); and tuple (A, B, C, D).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As I intended the guarantees I have written, what you described here would still be backwards-compatible to introduce, because that particular ordering is just one among the many different orderings that the guarantees allow the compiler to choose. As for the struct, you also can't transmute between different #[repr(Rust)] structs with the same fields either.

I would be happy to elaborate on this in the text though.

Copy link
Member

Choose a reason for hiding this comment

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

I see, I misunderstood "have the same layout guarantees as a struct with the same fields". I over-read this to mean "have the same layout as a struct with the same fields". Thanks for clarifying! Still, I can imagine this documentation going stale: if we provide more guarantees for structs in the future, we wouldn't necessarily match those guarantees for tuples.

Copy link
Contributor

Choose a reason for hiding this comment

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

I tend to think that tuples and tuple structs ought to have analogous layout. The UCG conversation at least came to that conclusion (we do discuss "tail references" as well). There was talk, as I recall, of making (T, T, T) sort of special case, to permit casting that to [T; 3].

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What do you think of the new phrasing?

@joshtriplett
Copy link
Member

@cramertj It looks like your concern didn't get registered; can you try again in a top-level comment?

@@ -86,9 +86,9 @@ String slices are a UTF-8 representation of characters that have the same layout

## Tuple Layout

Tuples do not have any guarantees about their layout.
Tuples are laid out according to the default representation.
Copy link
Member

Choose a reason for hiding this comment

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

What does "the default representation" refer to here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The section with most of my changes has the heading "The Default Representation", and that's what I'm referring to. I don't know if there's a better way to phrase it, or perhaps add a link to the heading?

Copy link
Member

Choose a reason for hiding this comment

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

+1 a link to the heading would be great, and with an explicit note that they may not be the same representation as a struct with equivalent fields.

@cramertj
Copy link
Member

@rfcbot concern tuple-layout

See #1152 (comment)

@Darksonn
Copy link
Contributor Author

What do I need to do to get this PR finished? I believe that the tuple-layout concern is resolved per the conversation above.

@cramertj
Copy link
Member

@rfcbot resolve tuple-layout

I think the intention is to clarify here that tuple layout and struct layout are not guaranteed to be the same. With that in mind, the rest of this looks great to me! Sorry for forgetting this thread for ages :(

@rfcbot
Copy link

rfcbot commented Aug 31, 2022

🔔 This is now entering its final comment period, as per the review above. 🔔

psst @joshtriplett, I wasn't able to add the final-comment-period label, please do so.

@ehuss ehuss added the S-waiting-on-author Status: The marked PR is awaiting some action (such as code changes) from the PR author. label Sep 1, 2022
@rfcbot
Copy link

rfcbot commented Sep 10, 2022

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.

This will be merged soon.

psst @joshtriplett, I wasn't able to add the finished-final-comment-period label, please do so.

Copy link
Contributor

@ehuss ehuss left a comment

Choose a reason for hiding this comment

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

Thanks! I pushed a commit to link to the default representation.

@ehuss ehuss merged commit d2acc38 into rust-lang:master Sep 19, 2022
@Darksonn Darksonn deleted the type-layout-repr-rust-field-alignment branch September 19, 2022 22:10
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Sep 21, 2022
Update books

## nomicon

1 commits in d880e6ac2acf133dce640da24b9fb692844f02d4..f53bfa056929217870a5d2df1366d2e7ba35096d
2022-08-24 12:42:34 -0700 to 2022-09-05 07:19:02 -0700
- Small typo (rust-lang/nomicon#379)

## reference

9 commits in f62e93c28323ed9637d0a205a0c256498674a509..a7cdac33ca7356ad49d5c2b5e2c5010889b33eee
2022-08-28 10:01:28 -0700 to 2022-09-19 17:39:58 -0700
- Clarify wording for references. (rust-lang/reference#1223)
- Update Unicode reference to match rustc implementation (rust-lang/reference#1271)
- Add documentation for raw-dylib and link_ordinal (rust-lang/reference#1244)
- Specify guarantees for repr(rust) structs (rust-lang/reference#1152)
- Classify AsyncBlockExpression as ExpressionWithoutBlock (rust-lang/reference#1268)
- Update closure-expr.md (rust-lang/reference#1269)
- Clarify that 0 is a valid multiple of a type's alignment (rust-lang/reference#1260)
- Remove `ne` from derive example (rust-lang/reference#1264)
- Clarify reference on async blocks (rust-lang/reference#1262)

## book

6 commits in 0a5421ceb238357b3634fb75234eba4d1dad643c..f1e5ad844d0c61738006cdef26227beeb136948e
2022-08-28 19:51:04 -0400 to 2022-09-19 09:48:21 -0400
- Fix punctuation in ch05-02
- Ownership move chapter link fix
- Wrong listing number
- Reword text around box
- `Box&lt;T&gt;` instead of "box"
- Update Clippy output in Appendix D

## rust-by-example

2 commits in 03301f8ae55fa6f20f7ea152a517598e6db2cdb7..767a6bd9727a596d7cfdbaeee475e65b2670ea3a
2022-08-14 08:51:44 -0300 to 2022-09-14 09:17:18 -0300
- struct_visibility.md:  Remove unneeded '#[allow(dead_code)]' (rust-lang/rust-by-example#1609)
- Fix assorted typos (rust-lang/rust-by-example#1601)

## rustc-dev-guide

15 commits in 04892c1a6fc145602ac7367945fda9d4ee83c9fb..f587d6e7cddeaa3cf0a33ec1e368df1a408fa0aa
2022-08-29 20:07:51 +0200 to 2022-09-20 07:43:59 +0900
- Update stability guide to use CURRENT_RUSTC_VERSION (rust-lang/rustc-dev-guide#1468)
- Add a note about building `rust-analyzer-proc-macro-srv` (rust-lang/rustc-dev-guide#1467)
- Link from "implementing to new features" to mcp.md (rust-lang/rustc-dev-guide#1465)
- remove stray **
- Explain the new valtree system for type level constants. (rust-lang/rustc-dev-guide#1097)
- fix typos and formatting
- Say "bootstrap" instead of "rustbuild"; the latter is not explained anywhere and is not much more clear.
- Rewrite the section on passing flags to subcommands
- Remove the diagram of all outputs generated by x.py
- "symbol names" =&gt; ABI
- Add symbol-addition to the how-to for new features (rust-lang/rustc-dev-guide#1457)
- Fix typo (rust-lang/rustc-dev-guide#1459)
- Document multipart_suggestion derive on SessionSubdiagnostic
- Add reference for updating Windows PATH and fix typo
- Update for removal of RLS (rust-lang/rustc-dev-guide#1450)

## embedded-book

1 commits in befe6840874311635c417cf731377f07234ee373..4ce51cb7441a6f02b5bf9b07b2eb755c21ab7954
2022-07-25 07:51:14 +0000 to 2022-09-15 08:53:09 +0000
- Create CITATION.bib (as per rust-embedded/book#327)  (rust-embedded/book#329)
JohnTitor added a commit to JohnTitor/rust that referenced this pull request Sep 22, 2022
Update books

## nomicon

1 commits in d880e6ac2acf133dce640da24b9fb692844f02d4..f53bfa056929217870a5d2df1366d2e7ba35096d
2022-08-24 12:42:34 -0700 to 2022-09-05 07:19:02 -0700
- Small typo (rust-lang/nomicon#379)

## reference

9 commits in f62e93c28323ed9637d0a205a0c256498674a509..a7cdac33ca7356ad49d5c2b5e2c5010889b33eee
2022-08-28 10:01:28 -0700 to 2022-09-19 17:39:58 -0700
- Clarify wording for references. (rust-lang/reference#1223)
- Update Unicode reference to match rustc implementation (rust-lang/reference#1271)
- Add documentation for raw-dylib and link_ordinal (rust-lang/reference#1244)
- Specify guarantees for repr(rust) structs (rust-lang/reference#1152)
- Classify AsyncBlockExpression as ExpressionWithoutBlock (rust-lang/reference#1268)
- Update closure-expr.md (rust-lang/reference#1269)
- Clarify that 0 is a valid multiple of a type's alignment (rust-lang/reference#1260)
- Remove `ne` from derive example (rust-lang/reference#1264)
- Clarify reference on async blocks (rust-lang/reference#1262)

## book

6 commits in 0a5421ceb238357b3634fb75234eba4d1dad643c..f1e5ad844d0c61738006cdef26227beeb136948e
2022-08-28 19:51:04 -0400 to 2022-09-19 09:48:21 -0400
- Fix punctuation in ch05-02
- Ownership move chapter link fix
- Wrong listing number
- Reword text around box
- `Box&lt;T&gt;` instead of "box"
- Update Clippy output in Appendix D

## rust-by-example

2 commits in 03301f8ae55fa6f20f7ea152a517598e6db2cdb7..767a6bd9727a596d7cfdbaeee475e65b2670ea3a
2022-08-14 08:51:44 -0300 to 2022-09-14 09:17:18 -0300
- struct_visibility.md:  Remove unneeded '#[allow(dead_code)]' (rust-lang/rust-by-example#1609)
- Fix assorted typos (rust-lang/rust-by-example#1601)

## rustc-dev-guide

15 commits in 04892c1a6fc145602ac7367945fda9d4ee83c9fb..f587d6e7cddeaa3cf0a33ec1e368df1a408fa0aa
2022-08-29 20:07:51 +0200 to 2022-09-20 07:43:59 +0900
- Update stability guide to use CURRENT_RUSTC_VERSION (rust-lang/rustc-dev-guide#1468)
- Add a note about building `rust-analyzer-proc-macro-srv` (rust-lang/rustc-dev-guide#1467)
- Link from "implementing to new features" to mcp.md (rust-lang/rustc-dev-guide#1465)
- remove stray **
- Explain the new valtree system for type level constants. (rust-lang/rustc-dev-guide#1097)
- fix typos and formatting
- Say "bootstrap" instead of "rustbuild"; the latter is not explained anywhere and is not much more clear.
- Rewrite the section on passing flags to subcommands
- Remove the diagram of all outputs generated by x.py
- "symbol names" =&gt; ABI
- Add symbol-addition to the how-to for new features (rust-lang/rustc-dev-guide#1457)
- Fix typo (rust-lang/rustc-dev-guide#1459)
- Document multipart_suggestion derive on SessionSubdiagnostic
- Add reference for updating Windows PATH and fix typo
- Update for removal of RLS (rust-lang/rustc-dev-guide#1450)

## embedded-book

1 commits in befe6840874311635c417cf731377f07234ee373..4ce51cb7441a6f02b5bf9b07b2eb755c21ab7954
2022-07-25 07:51:14 +0000 to 2022-09-15 08:53:09 +0000
- Create CITATION.bib (as per rust-embedded/book#327)  (rust-embedded/book#329)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-author Status: The marked PR is awaiting some action (such as code changes) from the PR author. T-lang Team: Lang
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Document field struct alignment guarantees?