@@ -292,11 +292,15 @@ apply, as described below.
292292
293293#### Discriminant elision on Option-like enums
294294
295- (Meta-note: The content in this section is not described by any RFC
296- and is therefore "non-normative".)
295+ (Meta-note: The content in this section is not fully described by any RFC and is
296+ therefore "non-normative". Parts of it were specified in
297+ [rust-lang/rust#60300]).
297298
298- **Definition.** An **option-like enum** is a 2-variant enum where:
299+ [rust-lang/rust#60300]: https://github.com/rust-lang/rust/pull/60300
299300
301+ **Definition.** An **option-like enum** is a 2-variant `enum` where:
302+
303+ - the `enum` has no explicit `#[repr(...)]`, and
300304- one variant has a single field, and
301305- the other variant has no fields (the "unit variant").
302306
@@ -309,26 +313,36 @@ field which it contains; in the case of `Option<T>`, the payload has
309313type `T`.
310314
311315**Definition.** In some cases, the payload type may contain illegal
312- values, which are called **niches**. For example, a value of type `&T`
313- may never be `NULL`, and hence defines a niche consisting of the
316+ values, which are called **[ niches][niche] **. For example, a value of type `&T`
317+ may never be `NULL`, and hence defines a [ niche] consisting of the
314318bitstring `0`. Similarly, the standard library types [`NonZeroU8`]
315319and friends may never be zero, and hence also define the value of `0`
316- as a niche. (Types that define niche values will say so as part of the
317- description of their validity invariant, which -- as of this writing
318- -- are the next topic up for discussion in the unsafe code guidelines
319- process.)
320+ as a [niche].
320321
321322[`NonZeroU8`]: https://doc.rust-lang.org/std/num/struct.NonZeroU8.html
322323
323- **Option-like enums where the payload defines at least one niche value
324+ The [niche] values must be disjoint from the values allowed by the validity
325+ invariant. The validity invariant is, as of this writing, the current active
326+ discussion topic in the unsafe code guidelines process. [rust-lang/rust#60300]
327+ specifies that the following types have at least one [niche] (the all-zeros
328+ bit-pattern):
329+
330+ * `&T`
331+ * `&mut T`
332+ * `extern "C" fn`
333+ * `core::num::NonZero*`
334+ * `core::ptr::NonNull<T>`
335+ * `#[repr(transparent)] struct` around one of the types in this list.
336+
337+ **Option-like enums where the payload defines at least one [niche] value
324338are guaranteed to be represented using the same memory layout as their
325339payload.** This is called **discriminant elision**, as there is no
326- explicit discriminant value stored anywhere. Instead, niche values are
340+ explicit discriminant value stored anywhere. Instead, [ niche] values are
327341used to represent the unit variant.
328342
329343The most common example is that `Option<&u8>` can be represented as an
330344nullable `&u8` reference -- the `None` variant is then represented
331- using the niche value zero. This is because a valid `&u8` value can
345+ using the [ niche] value zero. This is because a valid `&u8` value can
332346never be zero, so if we see a zero value, we know that this must be
333347`None` variant.
334348
@@ -351,6 +365,19 @@ enum Enum1<T> {
351365}
352366```
353367
368+ ** Example.** The following enum definition is ** not** option-like,
369+ as it has an explicit ` repr ` attribute.
370+
371+ ``` rust
372+ #[repr(u8 )]
373+ enum Enum2 <T > {
374+ Present (T ),
375+ Absent1 ,
376+ }
377+ ```
378+
379+ [niche]: ../glossary.html#niche
380+
354381## Unresolved questions
355382
356383### Layout of single variant enums
0 commit comments