Yes, that's the difference between using #[derive(SomeDeriveMacro)]
and #[some_proc_macro_attr]
: while the former only gets to peek / read at the input struct/enum/union
definition (including the #[B]
and #[C]
attrs), a proc-macro attribute acts like a function-like macro in that regard:
#[some_macro_attr]
… some item …
could always be written as:
some_function_like_macro! {
… some item …
}
-
in that regard, by the way, there is a proc-macro attribute that does exactly that: it takes a macro_rules!
macro parameter, and just expands to a call to that macro with the item as input:
#[macro_rules_attribute(some_macro!)]
That is, the item definition is just an input given to the macro, which gets to emit whatever it wants. When you thing about this, by the way, that power is already showcased by the #[cfg(…)]
attributes: they're either the identity macro (re-emitting the input as-is), or they are a "nullifying" macro which ignores its input and expand to nothingness.
In practice, however, a proc-macro will likely interact with its input, often leaving it be, or sometimes mutating it a bit, but it is important to be aware of this: that function-like and attribute macros can emit whatever they want, disregarding or mutating their input.