rust-lang / rust-lang/rust

Diagnostic refers to ambigous `x.0` enum field

Open
#150,144 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-diagnostics T-compiler
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

Code
// in upstream library crate1

#[non_exhaustive]
pub enum Meow {
    A(u32, String),
}

// in a downstream crate

use crate1::Meow;

pub fn f(x: Meow) -> impl FnOnce() {
    || {
        match x {
            Meow::A(a, b) => {
                drop((a, b));
            }
            _ => unreachable!(),
        }
    }
}
Current output
error[E0373]: closure may outlive the current function, but it borrows `x.0`, which is owned by the current function
  --> src/main.rs:8:5
   |
 8 |     || {
   |     ^^ may outlive borrowed value `x.0`
 9 |         match x {
   |               - `x.0` is borrowed here
   |
note: closure is returned here
  --> src/main.rs:8:5
   |
 8 | /     || {
 9 | |         match x {
10 | |             Meow::A(a, b) => {
11 | |                 drop((a, b));
...  |
15 | |     }
   | |_____^
help: to force the closure to take ownership of `x.0` (and any other referenced variables), use the `move` keyword
   |
 8 |     move || {
   |     ++++

For more information about this error, try `rustc --explain E0373`.
Desired output

I’m not sure. Maybe refer to “the discriminant of x x.Meow.0 instead of x.0?

Edit: I was wrong about this being the discriminant

Rationale and extra context

This code compiles without error on Stable 1.92.0.

The diagnostic in current Nightly refers to x.0. At first glance I’m not sure what that means, and if I write it in code rustc agrees: error[E0609]: no field `0` on type `Meow`

This test case is from https://github.com/rust-lang/reference/pull/1837#discussion_r2630423434 which refers to https://github.com/rust-lang/rust/pull/138961. (That PR landed recently so it’s not part of 1.92.0.) There we can read:

The breaking change

During closure capture analysis, matching an enum against a constructor is considered to require inspecting a discriminant if the enum has more than one variant. Notably, this is the case even if all the other variants happen to be uninhabited.

So it sounds like x.0 really means “the discriminant of x

Edit: I was wrong

Rust Version
rustc 1.94.0-nightly (fcf67da03 2025-12-18)
binary: rustc
commit-hash: fcf67da039f42e3905cf6f69e33304299c45149f
commit-date: 2025-12-18
host: x86_64-unknown-linux-gnu
release: 1.94.0-nightly
LLVM version: 21.1.8

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the reproducer in src/main.rs and compare the diagnostic produced by the nightly compiler with Stable 1.92.0. Read the closure-capture behavior described in rust-lang/rust#138961 and the linked reference discussion. Done means the diagnostic identifies the captured place without misleadingly presenting x.0 as a usable field, with regression coverage for this case.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.