Expand description
A utility macro to prefix each of several statements with the given tokens.
Doing this with items is straightforward: the item
fragment specifier
in macro_rules! works as expected.
With statements however, things get tricky. Since the stmt
fragment specifier
also matches lone semicolons (which are no-op statements), and doesn’t match trailing
semicolons, the solution isn’t trivial.
After getting around the limitation, you’ll be surprised to find the Rust compiler gets really
confused with cryptic errors despite everything seeming right. After much trial and error, I
found a procedural macro with special logic for
Delimiter::None seems to work right.
This macro is implemented as prefix_stmts!. It’s a wrapper around the actual implementation,
which first separates input statements through the stmt
fragment specifier,
and then forwards them to a procedural macro
(emit_prefixed_tokens_except_starts_with_semicolon),
which does exactly what the name says (with the Delimiter::None
trick).
If you find a way to do this without a procedural macro, please do let me know!
use prefix_stmts::prefix_stmts;
fn void() {}
let mut count: usize = 0;
prefix_stmts! {
[ count += 1; ]
;;;;;;;;;;;;;;;;; // Lone semicolons (noop, don't prefix)
pub(crate) fn foo() {}
let _: usize = 42;
void();
{ foo();; void() };;;
{ ( { void() } );; foo() }
}
assert_eq!(count, 5);My whole motivation for making this was allowing several statements to be prefixed with
cfg
attributes without repeating the attribute for each statement.
use prefix_stmts::prefix_stmts;
prefix_stmts! {
[ #[cfg( all() )] ]
const FOO: bool = true;
}
prefix_stmts! {
[ #[cfg( not( all() ) )] ]
const FOO: bool = false;
}
assert_eq!(FOO, true);The Minimum Supported Rust Version (MSRV) for this crate is Rust 1.45, which added support for statements emitted by procedural macros. Do mind that Rust <= 1.47 has issues with hygiene from the procedural macro, so using at least Rust 1.48 is recommended.
Macros§
- prefix_
stmts - Prefixes each statement with the given prefix tokens. First provide the tokens to prefix wrapped
in
[ brackets ], then follow with the statements.