Attribute Macro apply
#[apply]
Expand description
Applies the given macro_rules!
macro to the decorated item.
This, as with any proc_macro_attribute
, consumes the item it
decorates: it is the macro_rules!
macro job to generate it (it is thus
able to modify it!).
For a version with “read-only” access to the item it decorates, see
macro_rules_derive
.
§Examples
§Deriving getters for a (non-generic) struct
Imagine having define the following handy make_getters!
(macro_rules!
)
macro:
macro_rules! make_getters {(
$(#[$struct_meta:meta])*
$struct_vis:vis
struct $StructName:ident {
$(
$(#[$field_meta:meta])*
$field_vis:vis // this visibility will be applied to the getters instead
$field_name:ident : $field_ty:ty
),* $(,)?
}
) => (
// First, generate the struct definition we have been given, but with
// private fields instead.
$(#[$struct_meta])*
$struct_vis
struct $StructName {
$(
$(#[$field_meta])*
// notice the lack of visibility => private fields
$field_name: $field_ty,
)*
}
// Then, implement the getters:
impl $StructName {
$(
#[inline]
$field_vis
fn $field_name (self: &'_ Self)
-> &'_ $field_ty
{
&self.$field_name
}
)*
}
)}
Basically allowing you to write:
use example::Person;
mod example {
make_getters! {
/// The macro handles meta attributes such as docstrings
pub
struct Person {
pub
name: String,
pub
age: u8,
}
}
}
fn is_new_born (person: &'_ mut Person)
-> bool
{
// Reading the value through the getter is fine…
return *person.age() == 0;
// But trying to mutate it by skipping the getter is not 💪
person.age = 0;
// ^ error[E0616]: field `age` of struct `example::Person` is private
}
This is fine, etc., but that rightward drift on make_getters! {
syntax
problematic:
-
Incurs in extra rightward drift and thus, noise.
-
Worse, it leads to a non-escalable / composable pattern: if we had a second macro, say
make_setters!
, our syntax is unable to handle both macros being called on the same type definition.
Hence ::macro_rules_attribute
’s #[apply]
(formerly called
#[macro_rules_attribute]
itself) helper:
#[macro_use]
extern crate macro_rules_attribute;
use example::Person;
mod example {
#[apply(make_getters!)] // or `#[apply(make_getters)]`: the final `!` is not mandatory
/// The macro handles meta attributes such as docstrings
pub
struct Person {
pub
name: String,
pub
age: u8,
}
}
fn is_new_born (person: &'_ Person)
-> bool
{
// Reading the value through the getter is fine…
*person.age() == 0
// But trying to mutate it by skipping the getter is not 💪
// person.age == 0
// ^ error[E0616]: field `age` of struct `example::Person` is private
}