- 
                Notifications
    You must be signed in to change notification settings 
- Fork 13.9k
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