-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Specify that "option-like" enums must be #[repr(Rust)]
to be ABI-compatible with their non-1ZST field.
#141947
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
Conversation
Add that the enum must be `#[repr(Rust)]` and not `#[repr(packed)]` or `#[repr(align)]` in order to be ABI-compatible with its null-pointer-optimized field.
Wording about |
I agree though that this needs review from r? lang |
/// - The enum `E` uses the [`Rust` representation], and is not modified by the `align` or | ||
/// `packed` representation modifiers. |
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.
Changing alignment of something can change its ABI, and both of these repr attributes, as modifiers, can do that. So I am okay with having the guarantee be conditional on any usage of the repr attributes. If T-lang wants us to guarantee that the attributes only invalidate the nullptr opt if they actually would result in a change in the alignment of the type, that may be doable, but it would require auditing the code involved and landing a number of tests, so I don't know that it should happen in this PR. Also, see my next comment.
@@ -1833,6 +1833,8 @@ mod prim_ref {} | |||
/// - If `T` is guaranteed to be subject to the [null pointer | |||
/// optimization](option/index.html#representation), and `E` is an enum satisfying the following | |||
/// requirements, then `T` and `E` are ABI-compatible. Such an enum `E` is called "option-like". | |||
/// - The enum `E` uses the [`Rust` representation], and is not modified by the `align` or | |||
/// `packed` representation modifiers. | |||
/// - The enum `E` has exactly two variants. | |||
/// - One variant has exactly one field, of type `T`. | |||
/// - All fields of the other variant are zero-sized with 1-byte alignment. |
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.
Reviewing more closely, I feel guaranteeing e.g. repr(align(2))
won't change the layout if T
is 2-aligned would be inconsistent with this clause.
We could potentially raise this alignment to whatever the alignment of T
is, for example. I don't want to alter the guarantee around the 1ZST case, however, as it places a number of annoying requirements on the implementation. Being able to special-case specifically on 1ZSTs simplifies a lot of things. I would be okay with guaranteeing that repr(align(1))
doesn't change anything, though, because it doesn't. There's also some inclarity about certain special cases around ZSTs already when they combine with other repr attributes like repr(C)
.
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.
To summarize my thoughts, this is fine with me as-is, speaking re: my (relative) familiarity with the layout code's bits and bobs.
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.
@rustbot labels +I-lang-nominated +P-lang-drag-1 +S-waiting-on-team
The diff looks right to me, and I agree with @workingjubilee's comments as well, but it would indeed be better for the team to have a look here first, so let's not merge this yet. This is the sort of thing where we all need to have a look at it, if nothing else, just to ensure we all keep context on what exactly we've said the rule is.
#[repr(Rust)]
to be ABI-compatibile with their non-1ZST field.#[repr(Rust)]
to be ABI-compatible with their non-1ZST field.
@traviscross Based on the triage meeting notes, lang had a fair vibe about this. Was there an intention to r+ this as a simple amendment/clarification to the prior decision, FCP it, or is there a further discussion that I maybe should show up for? I think if lang is happy with this except with the |
Thanks, yes, I mentioned in the call I was going to... @bors r=workingjubilee,traviscross rollup |
…traviscross Specify that "option-like" enums must be `#[repr(Rust)]` to be ABI-compatible with their non-1ZST field. Add that the enum must be `#[repr(Rust)]` and not `#[repr(packed)]` or `#[repr(align)]` in order to be ABI-compatible with its null-pointer-optimized field. The specific rules here were decided on here: rust-lang#130628 (comment) but `repr` was not mentioned. In practice, only `#[repr(Rust)]` (or no `repr` attribute, which is equivalent) works for this, so add that to the docs. ----- Restrict to `#[repr(Rust)]` only, since: * `#[repr(C)]` and the primitive representations (`#[repr(u8)]` etc) definitely disqualify the enum from NPO, since they have defined layouts that store the tag separately to the payload. * `#[repr(transparent)]` enums are covered two bullet points above this (line 1830), and cannot have multiple variants, so would fail the "The enum has exactly two variants" requirement anyway. As for `#[repr(align)]`: my current wording that it is completely disallowed may be too strong: it seems like `#[repr(align(<= alignment of T))] enum Foo { X, Y(T) }` currently does still have the same ABI as `T` in practice, though this may not be something we want to promise. (`#[repr(align(> alignment of T))]` definitely disqualifies the enum from being ABI-compatible with T currently). I added the note about `packed` to match `align`, but `#[repr(packed)]` currently can't be applied to `enum`s at all anyway, so might be unnecessary. ----- I think this needs T-lang approval? cc `@workingjubilee`
…traviscross Specify that "option-like" enums must be `#[repr(Rust)]` to be ABI-compatible with their non-1ZST field. Add that the enum must be `#[repr(Rust)]` and not `#[repr(packed)]` or `#[repr(align)]` in order to be ABI-compatible with its null-pointer-optimized field. The specific rules here were decided on here: rust-lang#130628 (comment) but `repr` was not mentioned. In practice, only `#[repr(Rust)]` (or no `repr` attribute, which is equivalent) works for this, so add that to the docs. ----- Restrict to `#[repr(Rust)]` only, since: * `#[repr(C)]` and the primitive representations (`#[repr(u8)]` etc) definitely disqualify the enum from NPO, since they have defined layouts that store the tag separately to the payload. * `#[repr(transparent)]` enums are covered two bullet points above this (line 1830), and cannot have multiple variants, so would fail the "The enum has exactly two variants" requirement anyway. As for `#[repr(align)]`: my current wording that it is completely disallowed may be too strong: it seems like `#[repr(align(<= alignment of T))] enum Foo { X, Y(T) }` currently does still have the same ABI as `T` in practice, though this may not be something we want to promise. (`#[repr(align(> alignment of T))]` definitely disqualifies the enum from being ABI-compatible with T currently). I added the note about `packed` to match `align`, but `#[repr(packed)]` currently can't be applied to `enum`s at all anyway, so might be unnecessary. ----- I think this needs T-lang approval? cc ``@workingjubilee``
…traviscross Specify that "option-like" enums must be `#[repr(Rust)]` to be ABI-compatible with their non-1ZST field. Add that the enum must be `#[repr(Rust)]` and not `#[repr(packed)]` or `#[repr(align)]` in order to be ABI-compatible with its null-pointer-optimized field. The specific rules here were decided on here: rust-lang#130628 (comment) but `repr` was not mentioned. In practice, only `#[repr(Rust)]` (or no `repr` attribute, which is equivalent) works for this, so add that to the docs. ----- Restrict to `#[repr(Rust)]` only, since: * `#[repr(C)]` and the primitive representations (`#[repr(u8)]` etc) definitely disqualify the enum from NPO, since they have defined layouts that store the tag separately to the payload. * `#[repr(transparent)]` enums are covered two bullet points above this (line 1830), and cannot have multiple variants, so would fail the "The enum has exactly two variants" requirement anyway. As for `#[repr(align)]`: my current wording that it is completely disallowed may be too strong: it seems like `#[repr(align(<= alignment of T))] enum Foo { X, Y(T) }` currently does still have the same ABI as `T` in practice, though this may not be something we want to promise. (`#[repr(align(> alignment of T))]` definitely disqualifies the enum from being ABI-compatible with T currently). I added the note about `packed` to match `align`, but `#[repr(packed)]` currently can't be applied to `enum`s at all anyway, so might be unnecessary. ----- I think this needs T-lang approval? cc ```@workingjubilee```
Rollup of 9 pull requests Successful merges: - #138016 (Added `Clone` implementation for `ChunkBy`) - #140770 (add `extern "custom"` functions) - #141162 (refactor `AttributeGate` and `rustc_attr!` to emit notes during feature checking) - #141474 (Add `ParseMode::Diagnostic` and fix multiline spans in diagnostic attribute lints) - #141947 (Specify that "option-like" enums must be `#[repr(Rust)]` to be ABI-compatible with their non-1ZST field.) - #142135 (docs: autogenerate compiler flag stubs based on -Zhelp) - #142252 (Improve clarity of `core::sync::atomic` docs about "Considerations" in regards to CAS operations) - #142337 (miri: add flag to suppress float non-determinism) - #142353 (compiler: Ease off the accelerator on `unsupported_calling_conventions`) r? `@ghost` `@rustbot` modify labels: rollup
…traviscross Specify that "option-like" enums must be `#[repr(Rust)]` to be ABI-compatible with their non-1ZST field. Add that the enum must be `#[repr(Rust)]` and not `#[repr(packed)]` or `#[repr(align)]` in order to be ABI-compatible with its null-pointer-optimized field. The specific rules here were decided on here: rust-lang#130628 (comment) but `repr` was not mentioned. In practice, only `#[repr(Rust)]` (or no `repr` attribute, which is equivalent) works for this, so add that to the docs. ----- Restrict to `#[repr(Rust)]` only, since: * `#[repr(C)]` and the primitive representations (`#[repr(u8)]` etc) definitely disqualify the enum from NPO, since they have defined layouts that store the tag separately to the payload. * `#[repr(transparent)]` enums are covered two bullet points above this (line 1830), and cannot have multiple variants, so would fail the "The enum has exactly two variants" requirement anyway. As for `#[repr(align)]`: my current wording that it is completely disallowed may be too strong: it seems like `#[repr(align(<= alignment of T))] enum Foo { X, Y(T) }` currently does still have the same ABI as `T` in practice, though this may not be something we want to promise. (`#[repr(align(> alignment of T))]` definitely disqualifies the enum from being ABI-compatible with T currently). I added the note about `packed` to match `align`, but `#[repr(packed)]` currently can't be applied to `enum`s at all anyway, so might be unnecessary. ----- I think this needs T-lang approval? cc ````@workingjubilee````
Rollup of 8 pull requests Successful merges: - #138016 (Added `Clone` implementation for `ChunkBy`) - #140770 (add `extern "custom"` functions) - #141162 (refactor `AttributeGate` and `rustc_attr!` to emit notes during feature checking) - #141474 (Add `ParseMode::Diagnostic` and fix multiline spans in diagnostic attribute lints) - #141947 (Specify that "option-like" enums must be `#[repr(Rust)]` to be ABI-compatible with their non-1ZST field.) - #142252 (Improve clarity of `core::sync::atomic` docs about "Considerations" in regards to CAS operations) - #142337 (miri: add flag to suppress float non-determinism) - #142353 (compiler: Ease off the accelerator on `unsupported_calling_conventions`) r? `@ghost` `@rustbot` modify labels: rollup
…traviscross Specify that "option-like" enums must be `#[repr(Rust)]` to be ABI-compatible with their non-1ZST field. Add that the enum must be `#[repr(Rust)]` and not `#[repr(packed)]` or `#[repr(align)]` in order to be ABI-compatible with its null-pointer-optimized field. The specific rules here were decided on here: rust-lang#130628 (comment) but `repr` was not mentioned. In practice, only `#[repr(Rust)]` (or no `repr` attribute, which is equivalent) works for this, so add that to the docs. ----- Restrict to `#[repr(Rust)]` only, since: * `#[repr(C)]` and the primitive representations (`#[repr(u8)]` etc) definitely disqualify the enum from NPO, since they have defined layouts that store the tag separately to the payload. * `#[repr(transparent)]` enums are covered two bullet points above this (line 1830), and cannot have multiple variants, so would fail the "The enum has exactly two variants" requirement anyway. As for `#[repr(align)]`: my current wording that it is completely disallowed may be too strong: it seems like `#[repr(align(<= alignment of T))] enum Foo { X, Y(T) }` currently does still have the same ABI as `T` in practice, though this may not be something we want to promise. (`#[repr(align(> alignment of T))]` definitely disqualifies the enum from being ABI-compatible with T currently). I added the note about `packed` to match `align`, but `#[repr(packed)]` currently can't be applied to `enum`s at all anyway, so might be unnecessary. ----- I think this needs T-lang approval? cc `````@workingjubilee`````
Rollup of 7 pull requests Successful merges: - #138016 (Added `Clone` implementation for `ChunkBy`) - #141162 (refactor `AttributeGate` and `rustc_attr!` to emit notes during feature checking) - #141474 (Add `ParseMode::Diagnostic` and fix multiline spans in diagnostic attribute lints) - #141947 (Specify that "option-like" enums must be `#[repr(Rust)]` to be ABI-compatible with their non-1ZST field.) - #142252 (Improve clarity of `core::sync::atomic` docs about "Considerations" in regards to CAS operations) - #142337 (miri: add flag to suppress float non-determinism) - #142353 (compiler: Ease off the accelerator on `unsupported_calling_conventions`) r? `@ghost` `@rustbot` modify labels: rollup
Rollup of 6 pull requests Successful merges: - #138016 (Added `Clone` implementation for `ChunkBy`) - #141162 (refactor `AttributeGate` and `rustc_attr!` to emit notes during feature checking) - #141474 (Add `ParseMode::Diagnostic` and fix multiline spans in diagnostic attribute lints) - #141947 (Specify that "option-like" enums must be `#[repr(Rust)]` to be ABI-compatible with their non-1ZST field.) - #142252 (Improve clarity of `core::sync::atomic` docs about "Considerations" in regards to CAS operations) - #142337 (miri: add flag to suppress float non-determinism) r? `@ghost` `@rustbot` modify labels: rollup
Rollup merge of #141947 - zachs18:patch-4, r=workingjubilee,traviscross Specify that "option-like" enums must be `#[repr(Rust)]` to be ABI-compatible with their non-1ZST field. Add that the enum must be `#[repr(Rust)]` and not `#[repr(packed)]` or `#[repr(align)]` in order to be ABI-compatible with its null-pointer-optimized field. The specific rules here were decided on here: #130628 (comment) but `repr` was not mentioned. In practice, only `#[repr(Rust)]` (or no `repr` attribute, which is equivalent) works for this, so add that to the docs. ----- Restrict to `#[repr(Rust)]` only, since: * `#[repr(C)]` and the primitive representations (`#[repr(u8)]` etc) definitely disqualify the enum from NPO, since they have defined layouts that store the tag separately to the payload. * `#[repr(transparent)]` enums are covered two bullet points above this (line 1830), and cannot have multiple variants, so would fail the "The enum has exactly two variants" requirement anyway. As for `#[repr(align)]`: my current wording that it is completely disallowed may be too strong: it seems like `#[repr(align(<= alignment of T))] enum Foo { X, Y(T) }` currently does still have the same ABI as `T` in practice, though this may not be something we want to promise. (`#[repr(align(> alignment of T))]` definitely disqualifies the enum from being ABI-compatible with T currently). I added the note about `packed` to match `align`, but `#[repr(packed)]` currently can't be applied to `enum`s at all anyway, so might be unnecessary. ----- I think this needs T-lang approval? cc ``````@workingjubilee``````
Add that the enum must be
#[repr(Rust)]
and not#[repr(packed)]
or#[repr(align)]
in order to be ABI-compatible with its null-pointer-optimized field.The specific rules here were decided on here: #130628 (comment) but
repr
was not mentioned. In practice, only#[repr(Rust)]
(or norepr
attribute, which is equivalent) works for this, so add that to the docs.Restrict to
#[repr(Rust)]
only, since:#[repr(C)]
and the primitive representations (#[repr(u8)]
etc) definitely disqualify the enum from NPO, since they have defined layouts that store the tag separately to the payload.#[repr(transparent)]
enums are covered two bullet points above this (line 1830), and cannot have multiple variants, so would fail the "The enum has exactly two variants" requirement anyway.As for
#[repr(align)]
: my current wording that it is completely disallowed may be too strong: it seems like#[repr(align(<= alignment of T))] enum Foo { X, Y(T) }
currently does still have the same ABI asT
in practice, though this may not be something we want to promise. (#[repr(align(> alignment of T))]
definitely disqualifies the enum from being ABI-compatible with T currently).I added the note about
packed
to matchalign
, but#[repr(packed)]
currently can't be applied toenum
s at all anyway, so might be unnecessary.I think this needs T-lang approval?
cc @workingjubilee