Skip to content

Closure captures are inconsistent between x and x @ _ irrefutable patterns #137553

@meithecatte

Description

@meithecatte

Background: apart from paths, another way to make use of the precise capture of variables by closures is with irrefutable patterns:

fn main() {
    let mut a = (21, 37);
    // only captures a.0, example compiles fine
    let mut f = || {
        let (ref mut x, _) = a;
        *x = 42;
    };
    a.1 = 69;
    f();
}

One would expect this to be equivalent to an if let or match that happens to be irrefutable. However, this isn't the case:

fn main() {
    let mut a = (21, 37);
    // captures the entirety of a, example doesn't pass borrow check
    let mut f = || {
        match a {
            (ref mut x, _) => *x = 42,
        }
    };
    a.1 = 69;
    f();
}

However, one can get the code to compile again by introducing a no-op @-pattern:

fn main() {
    let mut a = (21, 37);
    // captures only a.0 again, and against all odds, the example compiles
    let mut f = || {
        match a {
            (ref mut x @ _, _) => *x = 42,
        }
    };
    a.1 = 69;
    f();
}

This suggests that the inconsistency is definitely a bug.

I have discovered this while investigating #137467, and I am working on resolving both issues. I am creating this issue to make it easy to keep track of the bug.

@rustbot claim

Meta

rustc --version --verbose:

rustc 1.87.0-nightly (f280acf4c 2025-02-19)
binary: rustc
commit-hash: f280acf4c743806abbbbcfe65050ac52ec4bdec0
commit-date: 2025-02-19
host: x86_64-unknown-linux-gnu
release: 1.87.0-nightly
LLVM version: 20.1.0

(git blame suggests that this behavior got introduced 3 years ago or so)

Metadata

Metadata

Assignees

Labels

A-closuresArea: Closures (`|…| { … }`)C-bugCategory: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language team

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions