Skip to content

2021 disjoint capture suggestion breaks macro_rules macro #88440

Open
@ehuss

Description

@ehuss

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-closuresArea: Closures (`|…| { … }`)A-edition-2021Area: The 2021 editionA-suggestion-diagnosticsArea: Suggestions generated by the compiler applied by `cargo fix`C-bugCategory: This is a bug.D-invalid-suggestionDiagnostics: A structured suggestion resulting in incorrect code.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions