diff --git a/text/0000-discriminant-bits.md b/text/0000-discriminant-bits.md new file mode 100644 index 00000000000..b7dfa897dcc --- /dev/null +++ b/text/0000-discriminant-bits.md @@ -0,0 +1,120 @@ +- Feature Name: discriminant_bits +- Start Date: 2019-04-01 +- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000) +- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000) + +# Summary +[summary]: #summary + +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. + +# Motivation +[motivation]: #motivation + +Rust encourages using enums to encode data with multiple variants. +An example of this can be found in the [game of life tutorial][game-of-life-tutorial]. + +```rust +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>()` is at least 1 byte. +For that reason, the Wasm book later goes on and replaces `Vec` by [`fixedbitset`][game-of-life-exercise], 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` 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. + +# Guide-level explanation +[guide-level-explanation]: #guide-level-explanation + +## Disciminant data + +`Discriminant::bit_size` is a method to retrieve the minimal number in bits necessary to represent this discriminant. + +```rust +const fn bit_size() -> usize; +``` + +This number is not subject to optimisation, so e.g. `Option<&str>` reports a bitsize of `1`. + +For example: + +```rust +enum Cell { + Dead = 0, + Alive = 1, +} + +enum RGB { + Red, + Green, + Blue +} + +Discriminant::bit_size() == 1 +Discriminant>::bit_size() == 1 +Discriminant::bit_size() == 2 +``` + +This information can be used to pack multiple discriminants easily for efficient storage and easy indexing. + +`Discriminant` gains the methods `into_bits` and `from_bits`: + +```rust +fn into_bits(&self) -> u128 +``` + +Returns a bit representation of the discriminant. +This data can be used to construct an efficient storage or index. + +```rust +fn from_bits(data: u128) -> Self +``` + +Creates a `Discriminant` from emitted bits usable for comparison. + +# Reference-level explanation +[reference-level-explanation]: #reference-level-explanation + +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. + +# Drawbacks +[drawbacks]: #drawbacks + +The added methods increase API surface in stdlib. + +# Rationale and alternatives +[rationale-and-alternatives]: #rationale-and-alternatives + +- 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_data` and `into_data` could instead be straight `From/Into` implementations +- Alternatively, `from/into_bits` could return a `Bits` type with a richer interface + +# Prior art +[prior-art]: #prior-art + +# Unresolved questions +[unresolved-questions]: #unresolved-questions + +- Naming of the functions could be improved. +- A basic implementation of a bitfield should be created during the implementation phase + +# Future possibilities +[future-possibilities]: #future-possibilities + +The feature is self-contained and I don't see direct extensions. + +[game-of-life-tutorial]: https://rustwasm.github.io/docs/book/game-of-life/implementing.html +[game-of-life-exercise]: https://rustwasm.github.io/docs/book/game-of-life/implementing.html#exercises