Until lifetimes of temporary variables are somehow fixed, I propose the following macro, which extends lifetimes by passing the value to a closure:
macro_rules! let_workaround {
(let $name:ident = $val:expr; $($rest:tt)+) => {
let f = |$name| { // naming closure avoids #[allow(clippy::redundant_closure_call)]
let_workaround! { $($rest)+ }
};
f($val)
};
($($rest:tt)+) => { $($rest)+ }
}
let_workaround! {
let a = format_args!(…);
let b = format_args!(…);
let c = format_args!(…);
// use a, b and c
}
Works like a charm! However if I optimize away the macro recursion, by passing all values to the same closure:
error: local ambiguity when calling macro `let_workaround`: multiple parsing options: built-in NTs tt ('rest') or 1 other option.
What's an NT (other than Microsoft’s old technology?) But more than the jargon, what's going on? Why doesn't the macro greedily gobble let statements, before drifting off into tt land?
Btw. not sure I actually want that in this concrete case, as it would prevent b from referencing a. But I stumbled over this while playing around, and it doesn't seem right.
NT presumably means "non-terminal" but yeah, I also just recently encountered this mysterious error – is it even meant to be seen by the user? It’s certainly vastly more opaque than your usual rustc error messages…
I don’t see any way to remove the recursion that doesn’t run into this error.
However, I want to propose an improvement to your macro/workaround approach: Instead of an immediately invoked closure, you can also use a match statement in order to extend temporary lifetimes.
Just turn let PATTERN = EXPR; REST into match EXPR { PATTERN => { REST } }, then temporaries from EXPR stay alive throughout REST.
The UI test is far more ambiguous than my literal let on the 1st path, vs. vague tt later. I guess I'm too much used to regex, where greedy match would dominate (and even backtrack when the submatch fails.)
I like your alternative though! Cleaner and no overzealous clippy to deal with. And the pat (on the back) makes this more useful than ident.