@@ -292,11 +292,15 @@ apply, as described below.
292
292
293
293
#### Discriminant elision on Option-like enums
294
294
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]).
297
298
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
299
300
301
+ **Definition.** An **option-like enum** is a 2-variant `enum` where:
302
+
303
+ - the `enum` has no explicit `#[repr(...)]`, and
300
304
- one variant has a single field, and
301
305
- the other variant has no fields (the "unit variant").
302
306
@@ -309,26 +313,36 @@ field which it contains; in the case of `Option<T>`, the payload has
309
313
type `T`.
310
314
311
315
**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
314
318
bitstring `0`. Similarly, the standard library types [`NonZeroU8`]
315
319
and 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].
320
321
321
322
[`NonZeroU8`]: https://doc.rust-lang.org/std/num/struct.NonZeroU8.html
322
323
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
324
338
are guaranteed to be represented using the same memory layout as their
325
339
payload.** 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
327
341
used to represent the unit variant.
328
342
329
343
The most common example is that `Option<&u8>` can be represented as an
330
344
nullable `&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
332
346
never be zero, so if we see a zero value, we know that this must be
333
347
`None` variant.
334
348
@@ -351,6 +365,19 @@ enum Enum1<T> {
351
365
}
352
366
```
353
367
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
+
354
381
## Unresolved questions
355
382
356
383
### Layout of single variant enums
0 commit comments