rust-lang / rust-lang/rust

Claims that deduced parameter to lambda has type &mut T, which makes calling functions that take a &mut T fail; actually making it arg: &mut T makes it work

Open
#151,066 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-coercions A-inference C-bug needs-triage T-compiler T-types
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

I tried this code:

pub type WalkedSample = (std::path::PathBuf, std::fs::File, ());
pub fn user((_, _, _): &mut WalkedSample) -> Result<(), String> { unimplemented!() }
pub fn gen() -> impl Iterator<Item = WalkedSample> { #[allow(unreachable_code)] vec![unimplemented!()].into_iter() }
fn main() -> Result<(), String> {
    let single = |bundle| -> Result<(), String> {
        user(bundle)?;
        user(bundle)?;
        Ok(())
    };
    for mut bundle in gen() {
        let _ = single(&mut bundle);
    }
    Ok(())
}

I expected to see this happen: it working

Instead, this happened:

error[E0382]: borrow of moved value: `bundle`
 --> a.rs:7:14
  |
5 |     let single = |bundle| -> Result<(), String> {
  |                   ------ move occurs because `bundle` has type `&mut (PathBuf, File, ())`, which does not implement the `Copy` trait
6 |         user(bundle)?;
  |              ------ value moved here
7 |         user(bundle)?;
  |              ^^^^^^ value borrowed here after move
  |
note: consider changing this parameter type in function `user` to borrow instead if owning the value isn't necessary
 --> a.rs:2:24
  |
2 | pub fn user((_, _, _): &mut WalkedSample) -> Result<(), String> { unimplemented!() }
  |        ----            ^^^^^^^^^^^^^^^^^ this parameter takes ownership of the value
  |        |
  |        in this function

error[E0597]: `bundle` does not live long enough
  --> a.rs:11:24
   |
10 |     for mut bundle in gen() {
   |         ---------- binding `bundle` declared here
11 |         let _ = single(&mut bundle);
   |                 ------ ^^^^^^^^^^^ borrowed value does not live long enough
   |                 |
   |                 borrow later used here
12 |     }
   |     - `bundle` dropped here while still borrowed

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0382, E0597.
For more information about an error, try `rustc --explain E0382`.

Obviously weird, since given let a: &mut T; fn f(&mut T);, f(a); f(a); is valid.

Even worse: if you do

    let single = |bundle: &mut WalkedSample| -> Result<(), String> {

this works.

So the deduced type is clearly not &mut WalkedSample, in spite of the diagnostic, because then it would've worked.

Meta

rustc --version --verbose:

rustc 1.92.0 (ded5c06cf 2025-12-08)
binary: rustc
commit-hash: ded5c06cf21d2b93bffd5d884aa6e96934ee4234
commit-date: 2025-12-08
host: x86_64-unknown-linux-gnu
release: 1.92.0
LLVM version: 21.1.3

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 by compiling the a.rs reproducer with the reported rustc 1.92.0 version and compare the inferred closure parameter with the explicitly annotated version. Investigate closure parameter inference and the resulting borrow errors; done means the unannotated form behaves like the annotated form without the reported move and lifetime errors.

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.