Skip to content

Commit f572fa7

Browse files
authored
Merge pull request #538 from RalfJung/option-like
update the docs for layout guarantees of option-like enums
2 parents c004f3a + 1f0ebd0 commit f572fa7

File tree

1 file changed

+20
-25
lines changed

1 file changed

+20
-25
lines changed

reference/src/layout/enums.md

+20-25
Original file line numberDiff line numberDiff line change
@@ -295,49 +295,44 @@ apply, as described below.
295295
296296
#### Discriminant elision on Option-like enums
297297
298-
(Meta-note: The content in this section is not fully described by any RFC and is
299-
therefore "non-normative". Parts of it were specified in
300-
[rust-lang/rust#60300]).
298+
(Meta-note: The content in this section have been turned into stable guarantees
299+
[via this
300+
FCP](https://github.com/rust-lang/rust/pull/130628#issuecomment-2402761599).).
301301
302-
[rust-lang/rust#60300]: https://github.com/rust-lang/rust/pull/60300
303-
304-
**Definition.** An **option-like enum** is a 2-variant `enum` where:
302+
**Definition.** The fully monomorphized form of a 2-variant `enum` is called an **option-like enum**
303+
if all of the following are satisfied:
305304
306305
- the `enum` has no explicit `#[repr(...)]`, and
307-
- one variant has a single field, and
308-
- the other variant has no fields (the "unit variant").
306+
- one variant has a single field with a type that guarantees discriminant
307+
elision (to be defined below), and
308+
- the other variant has only 1-ZST fields (the "unit variant").
309309
310310
The simplest example is `Option<T>` itself, where the `Some` variant
311311
has a single field (of type `T`), and the `None` variant has no
312-
fields. But other enums that fit that same template fit.
312+
fields. But other enums that fit that same template also qualify, e.g.
313+
`Result<T, ()>` or `Result<(), T>`.
313314
314315
**Definition.** The **payload** of an option-like enum is the single
315316
field which it contains; in the case of `Option<T>`, the payload has
316317
type `T`.
317318
318-
**Definition.** In some cases, the payload type may contain illegal
319-
values, which are called **[niches][niche]**. For example, a value of type `&T`
320-
may never be `NULL`, and hence defines a [niche] consisting of the
321-
bitstring `0`. Similarly, the standard library types [`NonZeroU8`]
322-
and friends may never be zero, and hence also define the value of `0`
323-
as a [niche].
324-
325-
[`NonZeroU8`]: https://doc.rust-lang.org/std/num/struct.NonZeroU8.html
326-
327-
The [niche] values must be disjoint from the values allowed by the validity
328-
invariant. The validity invariant is, as of this writing, the current active
329-
discussion topic in the unsafe code guidelines process. [rust-lang/rust#60300]
330-
specifies that the following types have at least one [niche] (the all-zeros
331-
bit-pattern):
319+
**Definition.** The following payload types have guaranteed discriminant
320+
elision:
332321
333322
* `&T`
334323
* `&mut T`
335-
* `extern "C" fn`
324+
* `Box<T>`
325+
* `extern "ABI" fn` (for arbitrary "ABI")
336326
* `core::num::NonZero*`
337327
* `core::ptr::NonNull<T>`
338328
* `#[repr(transparent)] struct` around one of the types in this list.
339329
340-
**Option-like enums where the payload defines at least one [niche] value
330+
(Meta-note: all these types have at least one bit pattern that is guaranteed be
331+
invalid, and can therefore be used as a "[niche]" when computing the enum layout.
332+
More types have this property, but the *guarantee* described here only applies
333+
to the types listed here.)
334+
335+
**Option-like enums where the payload has guaranteed discriminant elision
341336
are guaranteed to be represented using the same memory layout as their
342337
payload.** This is called **discriminant elision**, as there is no
343338
explicit discriminant value stored anywhere. Instead, [niche] values are

0 commit comments

Comments
 (0)