Crate prefix_stmts

Crate prefix_stmts 

Source
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.