- Feature Name: discriminant_bits
- Start Date: 2019-04-01
- RFC PR: rust-lang/rfcs#0000
- Rust Issue: rust-lang/rust#0000
Add methods to std::mem::Discriminant which inform of the space necessary for a bitwise representation of an enum's discriminant and the bits itself in an opaque fashion.
Rust encourages using enums to encode data with multiple variants. An example of this can be found in the game of life tutorial.
enum Cell {
Dead = 0,
Alive = 1
}Using these enums in collections is wasteful, as each instance reserves at least 1 byte of space.
Similarly, std::mem::size_of<Discriminant<Cell>>() is at least 1 byte.
For that reason, the Wasm book later goes on and replaces Vec<Cell> by fixedbitset, ending up with a much less intuitive implementation.
If it were possible to read the exact necessary size and the bit representation the descriminant, we could have a PackedBits<T> that uses exactly as much space as necessary.
This allows for an efficient representation of discriminant sets, which is both useful for simple enums, but also for crating an index of all discriminant values present in collection.
Discriminant::bit_size is a method to retrieve the minimal number in bits necessary to represent this discriminant.
const fn bit_size() -> usize;This number is not subject to optimisation, so e.g. Option<&str> reports a bitsize of 1.
For example:
enum Cell {
Dead = 0,
Alive = 1,
}
enum RGB {
Red,
Green,
Blue
}
Discriminant<Cell>::bit_size() == 1
Discriminant<Option<&str>>::bit_size() == 1
Discriminant<RGB>::bit_size() == 2This information can be used to pack multiple discriminants easily for efficient storage and easy indexing.
Discriminant<T> gains the methods into_bits and from_bits:
fn into_bits(&self) -> u128Returns a bit representation of the discriminant. This data can be used to construct an efficient storage or index.
fn from_bits(data: u128) -> SelfCreates a Discriminant from emitted bits usable for comparison.
The feature may interact with non-exhaustive enums. In this case, still, the currently used discriminant size should be used.
Adding the proposed functions probably entails adding a new compiler intrinsic discriminant_size.
Empty enums are of size 0.
The added methods increase API surface in stdlib.
- Why is this design the best in the space of possible designs?
- What other designs have been considered and what is the rationale for not choosing them?
- What is the impact of not doing this?
from_dataandinto_datacould instead be straightFrom/Intoimplementations- Alternatively,
from/into_bitscould return aBits<T>type with a richer interface
- Naming of the functions could be improved.
- A basic implementation of a bitfield should be created during the implementation phase
The feature is self-contained and I don't see direct extensions.