- 
                Notifications
    You must be signed in to change notification settings 
- Fork 13.9k
Open
Labels
A-closuresArea: Closures (`|…| { … }`)Area: Closures (`|…| { … }`)C-bugCategory: This is a bug.Category: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language teamRelevant to the language team
Description
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 (`|…| { … }`)Area: Closures (`|…| { … }`)C-bugCategory: This is a bug.Category: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language teamRelevant to the language team