@@ -295,49 +295,43 @@ apply, as described below.
295
295
296
296
#### Discriminant elision on Option-like enums
297
297
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]).
301
-
302
- [rust-lang/rust#60300]: https://github.com/rust-lang/rust/pull/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).).
303
301
304
302
**Definition.** An **option-like enum** is a 2-variant `enum` where:
305
303
306
304
- 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").
305
+ - one variant has a single field with a type that guarantees discriminant
306
+ elision (to be defined below), and
307
+ - the other variant has only 1-ZST fields (the "unit variant").
309
308
310
309
The simplest example is `Option<T>` itself, where the `Some` variant
311
310
has a single field (of type `T`), and the `None` variant has no
312
- fields. But other enums that fit that same template fit.
311
+ fields. But other enums that fit that same template also qualify, e.g.
312
+ `Result<T, ()>` or `Result<(), T>`.
313
313
314
314
**Definition.** The **payload** of an option-like enum is the single
315
315
field which it contains; in the case of `Option<T>`, the payload has
316
316
type `T`.
317
317
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):
318
+ **Definition.** The following payload types have guaranteed discriminant
319
+ elision:
332
320
333
321
* `&T`
334
322
* `&mut T`
335
- * `extern "C" fn`
323
+ * `Box<T>`
324
+ * `extern "ABI" fn` (for arbitrary "ABI")
336
325
* `core::num::NonZero*`
337
326
* `core::ptr::NonNull<T>`
338
327
* `#[repr(transparent)] struct` around one of the types in this list.
339
328
340
- **Option-like enums where the payload defines at least one [niche] value
329
+ (Meta-note: all these types have at least one bit pattern that is guaranteed be
330
+ invalid, and can therefore be used as a "[niche]" when computing the enum layout.
331
+ More types have this property, but the *guarantee* described here only applies
332
+ to the types listed here.)
333
+
334
+ **Option-like enums where the payload has guaranteed discriminant elision
341
335
are guaranteed to be represented using the same memory layout as their
342
336
payload.** This is called **discriminant elision**, as there is no
343
337
explicit discriminant value stored anywhere. Instead, [niche] values are
0 commit comments