rustc_data_structures

Macro impl_tag

source
macro_rules! impl_tag {
    (
        impl Tag for $Self:ty;
        $(
            $($path:ident)::* $( { $( $fields:tt )* })?,
        )*
    ) => { ... };
}
Expand description

Implements Tag for a given type.

You can use impl_tag on structs and enums. You need to specify the type and all its possible values, which can only be paths with optional fields.

§Examples

Basic usage:

#![feature(macro_metavar_expr)]
use rustc_data_structures::{impl_tag, tagged_ptr::Tag};

#[derive(Copy, Clone, PartialEq, Debug)]
enum SomeTag {
    A,
    B,
    X { v: bool },
    Y(bool, bool),
}

impl_tag! {
    // The type for which the `Tag` will be implemented
    impl Tag for SomeTag;
    // You need to specify all possible tag values:
    SomeTag::A, // 0
    SomeTag::B, // 1
    // For variants with fields, you need to specify the fields:
    SomeTag::X { v: true  }, // 2
    SomeTag::X { v: false }, // 3
    // For tuple variants use named syntax:
    SomeTag::Y { 0: true,  1: true  }, // 4
    SomeTag::Y { 0: false, 1: true  }, // 5
    SomeTag::Y { 0: true,  1: false }, // 6
    SomeTag::Y { 0: false, 1: false }, // 7
}

// Tag values are assigned in order:
assert_eq!(SomeTag::A.into_usize(), 0);
assert_eq!(SomeTag::X { v: false }.into_usize(), 3);
assert_eq!(SomeTag::Y(false, true).into_usize(), 5);

assert_eq!(unsafe { SomeTag::from_usize(1) }, SomeTag::B);
assert_eq!(unsafe { SomeTag::from_usize(2) }, SomeTag::X { v: true });
assert_eq!(unsafe { SomeTag::from_usize(7) }, SomeTag::Y(false, false));

Structs are supported:

#![feature(macro_metavar_expr)]
#[derive(Copy, Clone)]
struct Flags { a: bool, b: bool }

impl_tag! {
    impl Tag for Flags;
    Flags { a: true,  b: true  },
    Flags { a: false, b: true  },
    Flags { a: true,  b: false },
    Flags { a: false, b: false },
}

Not specifying all values results in a compile error:

#![feature(macro_metavar_expr)]
#[derive(Copy, Clone)]
enum E {
    A,
    B,
}

impl_tag! {
    impl Tag for E;
    E::A,
}