Skip to content

Update discriminant-elision optimization on Option-like enums #149

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

Merged
merged 12 commits into from
Jul 18, 2019
Merged
15 changes: 14 additions & 1 deletion reference/src/glossary.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,22 @@ Moreover, the layout of a type records its *function call ABI* (or just *ABI* fo
Note: Originally, *layout* and *representation* were treated as synonyms, and Rust language features like the `#[repr]` attribute reflect this.
In this document, *layout* and *representation* are not synonyms.

#### Niche

Invalid bit-patterns that will be used by layout optimizations.

For example, `&mut T` has at least one niche, the "all zeros" bit-pattern. This
niche is used by layout optimizations like "`enum` discriminant elision" to
guarantee that `Option<&mut T>` has the same size as `&mut T`.

While all niches are invalid bit-patterns, not all invalid bit-patterns are
niches. For example, the "all bits uninitialized" is an invalid bit-pattern for
`&mut T`, but this bit-pattern is not used by layout optimizations, and is not a
niche.


### TODO

* *niche*
* *tag*
* *rvalue*
* *lvalue*
Expand Down
39 changes: 32 additions & 7 deletions reference/src/layout/enums.md
Original file line number Diff line number Diff line change
Expand Up @@ -292,11 +292,15 @@ apply, as described below.

#### Discriminant elision on Option-like enums

(Meta-note: The content in this section is not described by any RFC
and is therefore "non-normative".)
(Meta-note: The content in this section is not fully described by any RFC and is
therefore "non-normative". Parts of it were specified in
[rust-lang/rust#60300]).

**Definition.** An **option-like enum** is a 2-variant enum where:
[rust-lang/rust#60300]: https://github.com/rust-lang/rust/pull/60300

**Definition.** An **option-like enum** is a 2-variant `enum` where:

- the `enum` has no explicit `#[repr(...)]`, and
- one variant has a single field, and
- the other variant has no fields (the "unit variant").

Expand All @@ -313,13 +317,23 @@ values, which are called **niches**. For example, a value of type `&T`
may never be `NULL`, and hence defines a niche consisting of the
bitstring `0`. Similarly, the standard library types [`NonZeroU8`]
and friends may never be zero, and hence also define the value of `0`
as a niche. (Types that define niche values will say so as part of the
description of their validity invariant, which -- as of this writing
-- are the next topic up for discussion in the unsafe code guidelines
process.)
as a niche.

[`NonZeroU8`]: https://doc.rust-lang.org/std/num/struct.NonZeroU8.html

The niche values must be disjoint from the values allowed by the validity
invariant. The validity invariant is, as of this writing, the current active
discussion topic in the unsafe code guidelines process. [rust-lang/rust#60300]
specifies that the following types have at least one niche (the all-zeros
bit-pattern):

* `&T`
* `&mut T`
* `extern "C" fn`
* `core::num::NonZero*`
* `core::ptr::NonNull<T>`
* `#[repr(transparent)] struct` around one of the types in this list.

**Option-like enums where the payload defines at least one niche value
are guaranteed to be represented using the same memory layout as their
payload.** This is called **discriminant elision**, as there is no
Expand Down Expand Up @@ -351,6 +365,17 @@ enum Enum1<T> {
}
```

**Example.** The following enum definition is **not** option-like,
as it has an explicit `repr` attribute.

```rust
#[repr(u8)]
enum Enum2<T> {
Present(T),
Absent1,
}
```

## Unresolved questions

### Layout of single variant enums
Expand Down