pub unsafe trait Phenotype {
type Value;
const NUM_VARIANTS: usize;
const BITS: usize;
const PEAPOD_SIZE: Option<usize>;
const IS_MORE_COMPACT: Option<bool>;
// Required methods
fn cleave(self) -> (usize, Self::Value);
unsafe fn reknit(tag: usize, value: Self::Value) -> Self;
}Expand description
This trait represents the behavior of an enum/tagged union.
Note: it should only be implemented with #[derive(Phenotype)]
§Safety
This trait is marked unsafe because extreme care must be taken to implement
it correctly. In particular, the reknit method can cause undefined behavior
if called with invalid inputs. Manual implementation of the trait is heavily
discouraged, but there may be cases (e.g. const generics) where it is necessary.
Required Associated Constants§
Sourceconst NUM_VARIANTS: usize
const NUM_VARIANTS: usize
The number of variants of the enum.
Sourceconst BITS: usize
const BITS: usize
The number of bits needed to represent every variant of the enum. For example, if the enum has 4 variants, then two bits are needed.
Sourceconst PEAPOD_SIZE: Option<usize>
const PEAPOD_SIZE: Option<usize>
The number of bits Phenotype uses to represent and instance of a type.
If the type Phenotype is being implemented for is generic,
this will be None, as sizes may vary accross different
generic parameters. For example, Type<usize> could be differently
sized than Type<[usize; 4]>
Sourceconst IS_MORE_COMPACT: Option<bool>
const IS_MORE_COMPACT: Option<bool>
Whether using Phenotype produces a more compact representation.
Will be Some(true) if implementations are the same size.
If the type Phenotype is being implemented for is generic,
this will be None, as sizes may vary accross different
generic parameters. For example, Type<usize> could be differently
sized than Type<[usize; 4]>
Required Associated Types§
Required Methods§
Sourcefn cleave(self) -> (usize, Self::Value)
fn cleave(self) -> (usize, Self::Value)
Takes an enum variant and cleaves it into a two parts:
a tag, and an union representing the data the enum can hold.
If the enum variant doesn’t hold data, None is returned as
the second tuple element.
Note: if the results of a call to cleave are not eventually
reknited, the destructor for the cleaveed enum will not run.
This can cause memory leaks. Types that manage heap memory often
implement cleanup and deallocation in their Drop implementations.
Sourceunsafe fn reknit(tag: usize, value: Self::Value) -> Self
unsafe fn reknit(tag: usize, value: Self::Value) -> Self
Takes a tag and a value and recombines them into a proper instance of an enum variant.
§Safety
Calling this function with incorrect inputs can result in undefined behavior. The tag must always match the state that the union is in.
For example, consider the following example
#[derive(Phenotype)]
enum UB {
U(usize), // -> tag = 0
B(bool) // -> tag = 1
}
// This is the type <UB as Phenotype>::Value
union Value {
U: usize,
B: bool
}
use peapod::Phenotype;
fn main {
let ub = UB::U(3);
let (_, data) = ub.cleave();
// ** DANGER **
// We are interpreting 3 as a bool! That's undefined behavior.
let BAD = <UB as Phenotype>::reknit(1, data);
}Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.