Is it possible to define a macro_rules macro that "uses" its input tokens but is otherwise a no-op?
Context: I'm converting some logging mechanisms to be controlled by features, including having no logging at all. In the case of no logging, the macros become no-ops; currently:
macro_rules! debug ( ($($tt:tt)*) => {{}} );
But then default method bodies that only use arguments to log trigger unused_variables, and imports that are only used in macro calls trigger unused_imports as well.
(cfg_attr isn't an adequate solution as I don't want to ignore actually-unmentioned imports and variables in any configuration.)
instead of expanding to "nothing", can you put the code under an if false {} branch? similar to how tracing::level_enabled!() is defined, which could short-circuits to the constant false depending on cargo feature flags.
What code, though? I can't output the code that relies on the non-present feature. I could try to ape every macro I suppose, but I'm hoping for something less onerous (and that wouldn't require ongoing changes to support new upstream invocation patterns).
ponders awhile
But I guess I don't even really want a no-op, and probably will need to ape the macros. Otherwise this works in the no-features case.
fn test() {
let mut s = String::new();
let r = &mut s;
debug!("{s}");
r;
}
So I need to use things in approximately the same way the featureful macros do, which in turn requires aping the macros.
oh, you have a different design. what I had in mind is the logging functions and types are always available, not feature gated, then the macro expands to a simple if statement.
but apparently, this does not work if the functions and types are conditional compiled.
// this is the implementation, could be generic or type-erased, etc.
// it is always available, not conditional compiled
pub fn _log_event<T: Event>(event: T) { ... }
// this is user-facing API
macro_rules! debug {
($($tt:tt)*) => {
// `is_debug()` can be const,
// possibly implemented with `cfg!(feature = "foobar")`
if is_debug() {
let event = $crate::DebugEvent::new(Instant::now(), file!(), line!(), format!($($tt)*));
$crate::_log_event(event)
}
}
}
Yeah, I guess I was unclear -- the macros come from a dependency iff some feature is enabled, and I just wanted to replace those with no-ops. But now I realize that's not really amenable to a robust API anyway.
I've just gone ahead and copied over the relevant macro_rules! patterns from upstream and that will have to do.