typewit

Macro type_fn

Source
macro_rules! type_fn {
    ($($args:tt)*) => { ... };
}
Expand description

Declares a type-level function (struct that implements TypeFn)

examples below

§Syntax

This section uses a macro_rules!-like syntax for the parameters that type_fn takes

$(#[$attrs:meta])*
$vis:vis struct $struct_name:ident $(< $struct_generics:generic_params >)?
$( where $struct_where_predicates:where_predicates  )?;
 
$(
    $(#[$impl_attrs:meta])*
    impl $(<$fn_generics:generic_params>)? $argument_type:ty => $return_type:ty
    $( where $fn_where_predicates:where_predicates  )?
);+
 
$(;)?

:where_predicates is a sequence of constraints. e.g: T: Foo, 'a: 'b, U: 'b.

:generic_params is a list of generic parameter declarations. e.g: 'a, T, #[cfg(feature = "hi")] U, const N: usize.

Generic parameters support the #[cfg(...)] attribute, no other attribute is supported.

§Generated code

This macro generates:

  • The struct declaration passed to the macro

  • A NEW associated constant for constructing the struct

  • Impls of TypeFn for the generated struct corresponding to each ... => ... argument.

If the struct has any lifetime or type parameters (even if disabled by #[cfg(...)] attributes), it has a private field, and requires using its NEW associated constant to be instantiated. If it has no type or lifetime parameters, the struct is a unit struct.

§Examples

This macro is also demonstrated in TypeEq::project, TypeEq::map, and the Indexing polymorphism root module example.

§Basic

use typewit::CallFn;
 
let item: CallFn<FnIterItem, Vec<&'static str>> = "hello";
let _: &'static str = item;
assert_eq!(item, "hello");
 
// Declares `struct FnIterItem`,
// a type-level function from `I` to `<I as IntoIterator>::Item`
typewit::type_fn!{
    struct FnIterItem;
 
    impl<I: IntoIterator> I => I::Item
}

§All syntax

Demonstrates all the syntax that this macro accepts and what it expands into:

typewit::type_fn! {
    /// Hello
    pub struct Foo<'a, T: IntoIterator = Vec<u8>, #[cfg(any())] const N: usize = 3>
    where T: Clone;
     
    /// docs for impl
    #[cfg(all())]
    impl<'b: 'a, U, #[cfg(all())] const M: usize> 
        [&'b U; M] => ([&'b U; M], T::IntoIter)
    where 
        U: 'static,
        u32: From<U>;
 
    /// docs for another impl
    impl () => T::Item
}

the above macro invocation generates code equivalent to this:

use typewit::TypeFn;
 
use core::marker::PhantomData;
 
/// Hello
// The `const N: usize = 3` param is removed by the `#[cfg(any()))]` attribute
pub struct Foo<'a, T: IntoIterator = Vec<u8>>(
    PhantomData<(&'a (), fn() -> T)>
) where T: Clone;
 
impl<'a, T: IntoIterator> Foo<'a, T>
where
    T: Clone,
{
    pub const NEW: Self = Self(PhantomData);
}
 
/// docs for impl
#[cfg(all())]
impl<'a, 'b: 'a, U, T: IntoIterator, #[cfg(all())] const M: usize> 
    TypeFn<[&'b U; M]> 
for Foo<'a, T>
where
    T: Clone,
    U: 'static,
    u32: From<U>
{
    type Output = ([&'b U; M], T::IntoIter);
}
 
/// docs for another impl
impl<'a, T: IntoIterator> TypeFn<()> for Foo<'a, T>
where
    T: Clone,
{
    type Output = T::Item;
}