I've written a proc macro that needs to know whether an ident is a variable, as opposed to a type, function or enum variant. It has some heuristics that work 90% of the time; the rest of the time it relies on explicit disambiguation by the programmer. I'd like to assert the correct inference has been made by statically asserting so in the output AST.
I'm currently using something like the following, which generally works, but it can in some cases introduce a borrowck error like the one below. Is there any implementation of assert_variable
that statically fails for assert_variable!(main)
and assert_variable!(None)
but succeeds for assert_variable!(x)
in this example?
macro_rules! assert_variable {
($var:ident) => {
#[allow(unreachable_code)]
{
if false {
$var = loop {};
}
}
}
}
fn main() {
// assert_variable!(main);
// assert_variable!(None);
let x = 10usize;
let _left = async {
assert_variable!(x);
};
let _right = async {
assert_variable!(x);
};
}
Errors:
Compiling playground v0.0.1 (/playground)
error[E0524]: two closures require unique access to `x` at the same time
--> src/main.rs:21:24
|
6 | $var = loop {};
| ----
| |
| first borrow occurs due to use of `x` in generator
| second borrow occurs due to use of `x` in generator
...
18 | let _left = async {
| _______________________-
19 | | assert_variable!(x);
20 | | };
| |_____- first closure is constructed here
21 | let _right = async {
| ________________________^
22 | | assert_variable!(x);
23 | | };
| |_____^ second closure is constructed here
24 | }
| - first borrow might be used here, when `_left` is dropped and runs the destructor for type `impl std::future::Future`
error: aborting due to previous error
error: could not compile `playground`.
To learn more, run the command again with --verbose.