macro_rules! type_fn { ($($args:tt)*) => { ... }; }
Expand description
Declares a type-level function (struct that implements TypeFn
)
§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;
}