Attribute Macro tylift::tylift[][src]

#[tylift]

The attribute promotes enum variants to their own types. The enum type becomes a kind – the type of a type – emulated by a trait, replacing the original type declaration. In Rust, the syntax of trait bounds (:) beautifully mirror the syntax of type annotations. Thus, the snippet B: Bool can also be read as “type parameter B of kind Bool”.

Traits representing kinds are sealed, which means nobody is able to add new types to the kind. Variants can hold (unnamed) fields of types of a given kind. Attributes (notably documentation comments) applied to the item itself and its variants will be preserved. Expanded code works in #![no_std]-environments.

As of right now, there is no automated way to reify the lifted variants (i.e. map them to their term-level counterpart). Lifted enum types can not be generic over kinds. Attributes placed in front of fields of a variant (constructor arguments) will not be translated and thus have no effect.

Examples:

use tylift::tylift;
use std::marker::PhantomData;

#[tylift]
pub enum Mode {
    Safe,
    Fast,
}

pub struct Text<M: Mode> {
    content: String,
    _marker: PhantomData<M>,
}

impl<M: Mode> Text<M> {
    pub fn into_inner(self) -> String {
        self.content
    }
}

impl Text<Safe> {
    pub fn from(content: Vec<u8>) -> Option<Self> {
        Some(Self {
            content: String::from_utf8(content).ok()?,
            _marker: PhantomData,
        })
    }
}

impl Text<Fast> {
    pub unsafe fn from(content: Vec<u8>) -> Self {
        Self {
            content: unsafe { String::from_utf8_unchecked(content) },
            _marker: PhantomData,
        }
    }
}

fn main() {
    let safe = Text::<Safe>::from(vec![0x73, 0x61, 0x66, 0x65]);
    let fast = unsafe { Text::<Fast>::from(vec![0x66, 0x61, 0x73, 0x74]) };
    assert_eq!(safe.map(Text::into_inner), Some("safe".to_owned()));
    assert_eq!(fast.into_inner(), "fast".to_owned());
}

#[tylift]
pub enum Bool {
    False,
    True,
}

#[tylift]
pub(crate) enum Nat {
    Zero,
    Succ(Nat),
}

#[tylift]
enum BinaryTree {
    Leaf,
    Branch(BinaryTree, Nat, BinaryTree),
}

#[tylift(mod)] // put the all 3 items into the module `Power`
pub enum Power {
    On,
    Off,
}

#[tylift(mod direction)] // put all 3 items into the module `direction`
pub(crate) enum Direction {
    /// Higher and higher!
    Up,
    /// Lower and lower...
    Down,
}