Skip to content

2021 disjoint capture suggestion breaks macro_rules macro #88440

Open

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

Activity

  1. added
    A-closuresArea: Closures (`|…| { … }`)
    C-bugCategory: This is a bug.
    A-suggestion-diagnosticsArea: Suggestions generated by the compiler applied by `cargo fix`
    D-invalid-suggestionDiagnostics: A structured suggestion resulting in incorrect code.
    on Aug 28, 2021
  2. arora-aman commented on Aug 28, 2021

    @arora-aman
    Contributor

    Some of my thought process:

    My initial thoughts were we can just issue warnings for any closure that has a precise capture given it was defined within a macro.

    Something like: Drop order/Trait might be affected, please check the edition guide on how to migrate. Without any specific suggestion and maybe we highlight macro a bit more in the edition guide.

    But we can have a case where capture_from_closure!(some_struct.some_vec)

    Hmm I suppose we will see this as precise capture.

    I guess during typechk can we tell that a piece of code is with a macro? And can issue a warning that's worded appropriately.

  3. arora-aman commented on Aug 30, 2021

    @arora-aman
    Contributor

    Maybe related to: #87955

  4. m-ou-se commented on Aug 31, 2021

    @m-ou-se
    Member

    rewrites the map call to:

            $e.map{ let _ = &decoded; (move |$v| $yld) }

    which is invalid syntax.

    The invalid syntax there is already fixed by #87958

    image

  5. added 3 commits that reference this issue on Sep 1, 2021
  6. added a commit that references this issue on Sep 2, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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