Description
I tried this code:
#![allow(unused)]
#![warn(rust_2021_incompatible_closure_captures)]
macro_rules! foo {
($v:ident) => {
move || {
println!("{:?}", $v.0);
}
};
}
fn main() {
let x = (vec![1], vec![2]);
foo!(x);
}
The rust_2021_incompatible_closure_captures lint generates a suggestion which causes this to fail to compile:
macro_rules! foo {
($v:ident) => {
move || {
let _ = &x; // ERROR: cannot find value `x` in this scope
println!("{:?}", $v.0);
}
};
}
I'm not exactly sure what this should do. In this particular case, the suggestion is not required. However, that's a fundamental problem with the rust_2021_incompatible_closure_captures
lint, as it does not know when it is required.
In general, modifying macros can be prone to failure, so maybe an alternative is to issue a warning with a non-machine-applicable fix when inside a macro_rules
definition?
This was found in the 2021 crater run for rcodec 1.0.1: https://crater-reports.s3.amazonaws.com/pr-87190-3/try%23a7a572ce3edd6d476191fbfe92c9c1986e009b34/reg/rcodec-1.0.1/log.txt
Note that this has even worse behavior than the example above. The sample macro:
macro_rules! forcomp_stmts {
{ $yld:block, $v:ident, $e:expr } => {
$e.map(move |$v| $yld)
};
{ $yld:block, $v:ident, $e:expr, $($tv:ident, $te:expr),+ } => {
$e.and_then(move |$v| {
forcomp_stmts!($yld, $($tv, $te),+)
})
};
}
rewrites the map call to:
$e.map{ let _ = &decoded; (move |$v| $yld) }
which is invalid syntax.
Meta
rustc --version --verbose
:
rustc 1.56.0-nightly (ac50a5335 2021-08-27)
binary: rustc
commit-hash: ac50a53359328a5d7f2f558833e63d59d372e4f7
commit-date: 2021-08-27
host: x86_64-apple-darwin
release: 1.56.0-nightly
LLVM version: 13.0.0
cc @rust-lang/wg-rfc-2229