macro_rules! define_family {
(@output_ty $Input:tt) => { ... };
(@output_ty $Input:tt, $Output:tt) => { ... };
(
root: $Root:ident,
$(#[$meta:meta])*
family: $vis:vis $Name:ident,
$(borrow: [$($borrow_lt:lifetime),* $(,)?],)?
input: $Input:ident,
$(output: $Output:ident ,)?
context: $Context:ty,
$(marker: [$($marker_gen:ident),* $(,)?],)?
$(bounds: [$($bounds:tt)*],)?
child: [
$($child:ident => $model:ty,)+
$(,)? ] $(,)?
) => { ... };
(
root: $Root:ident,
$(#[$meta:meta])*
family: $vis:vis $Name:ident,
$(borrow: [$($borrow_lt:lifetime),* $(,)?],)?
input: $Input:ident,
$(output: ($($Output:ident),+) ,)?
context: $Context:ty,
$(marker: [$($marker_gen:ident),* $(,)?],)?
$(bounds: [$($bounds:tt)*],)?
child: [
$($child:ident => $model:ty,)+
$(,)? ] $(,)?
) => { ... };
(
root: $Root:ident,
$(#[$meta:meta])*
family: $vis:vis $Name:ident,
$(borrow: [$($borrow_lt:lifetime),* $(,)?],)?
input: ($($Input:ident),+),
$(output: $Output:ident ,)?
context: $Context:ty,
$(marker: [$($marker_gen:ident),* $(,)?],)?
$(bounds: [$($bounds:tt)*],)?
child: [
$($child:ident => $model:ty,)+
$(,)? ] $(,)?
) => { ... };
(
root: $Root:ident,
$(#[$meta:meta])*
family: $vis:vis $Name:ident,
$(borrow: [$($borrow_lt:lifetime),* $(,)?],)?
input: ($($Input:ident),+),
$(output: ($($Output:ident),+) ,)?
context: $Context:ty,
$(marker: [$($marker_gen:ident),* $(,)?],)?
$(bounds: [$($bounds:tt)*],)?
child: [
$($child:ident => $model:ty,)+
$(,)? ] $(,)?
) => { ... };
(
root: $Root:ident,
$(#[$meta:meta])*
family: $vis:vis $Name:ident,
$(borrow: [$($borrow_lt:lifetime),* $(,)?],)?
input: $Input:ident,
$(output: $Output:ident ,)?
$(bounds: [$($bounds:tt)*],)?
child: [
$($child:ident => $model:ty,)+
$(,)? ] $(,)?
) => { ... };
(
root: $Root:ident,
$(#[$meta:meta])*
family: $vis:vis $Name:ident,
$(borrow: [$($borrow_lt:lifetime),* $(,)?],)?
input: $Input:ident,
$(output: ($($Output:ident),+) ,)?
$(bounds: [$($bounds:tt)*],)?
child: [
$($child:ident => $model:ty,)+
$(,)? ] $(,)?
) => { ... };
(
root: $Root:ident,
$(#[$meta:meta])*
family: $vis:vis $Name:ident,
$(borrow: [$($borrow_lt:lifetime),* $(,)?],)?
input: ($($Input:ident),+),
$(output: $Output:ident ,)?
$(bounds: [$($bounds:tt)*],)?
child: [
$($child:ident => $model:ty,)+
$(,)? ] $(,)?
) => { ... };
(
root: $Root:ident,
$(#[$meta:meta])*
family: $vis:vis $Name:ident,
$(borrow: [$($borrow_lt:lifetime),* $(,)?],)?
input: ($($Input:ident),+),
$(output: ($($Output:ident),+) ,)?
$(bounds: [$($bounds:tt)*],)?
child: [
$($child:ident => $model:ty,)+
$(,)? ] $(,)?
) => { ... };
}Expand description
Declares a concrete plugin family implementation for a given family root.
This macro generates:
- A family marker struct representing a concrete implementation of a plugin family.
- An implementation of the family root trait mapping each declared child operation to a concrete plugin model.
The generated family struct is purely a type-level marker and contains
no runtime data. It is used to bind concrete plugin models to a specific
(FamilyType, Child) combination through associated types.
When borrow are specified, the generated family marker stores them
in PhantomData fields so the type system correctly tracks them
without affecting runtime behavior.
§Syntax
§Family With Context
ⓘ
define_family! {
root: FamilyRoot, // Required: family root trait
family: pub MyFamily, // Required: visibility and concrete family marker struct
borrow: ['a], // Optional: lifetime parameters for family marker
input: Input, // Required: input type parameter
output: Output, // Optional: output type (defaults to input if omitted)
context: MyContext, // Required: context type
marker: [T], // Optional: generic parameters for the context
bounds: [T: Clone], // Optional: trait bounds for the generated impl
child: [ // Required: child -> model mapping
OperationA => ModelA,
OperationB => ModelB,
]
}§Family Without Context
ⓘ
define_family! {
root: FamilyRoot, // Required: family root trait
family: pub MyFamily, // Required: visibility and concrete family marker struct
borrow: ['a], // Optional: lifetime parameters for family marker
input: Input, // Required: input type parameter
output: Output, // Optional: output type (defaults to input if omitted)
bounds: [T: Clone], // Optional: trait bounds for the generated impl
child: [ // Required: child -> model mapping
OperationA => ModelA,
OperationB => ModelB,
]
}In the second form, the context parameter of the root trait defaults to ().
§Lifetimes and Generics
borrowapply to the family marker type- used to model execution-time borrowing
- stored via
PhantomData
ⓘ
borrow: ['a]markerapply only when acontextis specified- used to parameterize the context type
- introduced on the generated
impl, not the family struct
ⓘ
context: MyContext,
marker: [T]When no context is provided:
- the context defaults to
() markeris not used
§Example
ⓘ
// ----- Crate A ------
declare_family! {
root: pub VotingFamily,
child: [Phragmen, STV]
}
// ----- Crate B ------
plugin_model! {
name: PhragmenModel,
...
}
plugin_model! {
name: STVModel,
...
}
define_family! {
root: VotingFamily,
family: pub RuntimeVoting,
input: AccountId,
output: Balance,
context: RuntimeContext,
child: [
Phragmen => PhragmenModel,
STV => STVModel,
]
}This binds the Phragmen and Approval operations of the
VotingFamily root to concrete plugin models for the
RuntimeVoting family implementation.