rust-lang / rust-lang/rust

nested mutable reference error

Open
#142,039 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-borrow-checker C-bug T-compiler
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

I tried this code (minified example, both lifetimes are required in the actual code):

struct Context<'a, 'b> {
    root: Item<'a>,
    path: Vec<&'b str>,
}

pub struct Item<'a> {
    pub items: HashMap<&'a str, Item<'a>>,
}

impl<'a, 'b> Context<'a, 'b> {
    fn find(&mut self) -> &mut Item<'a> {
        let mut res = &mut self.root;
        for seg in &self.path {
            res = res.items.get_mut(seg).unwrap();
        }
        res
    }
}

I expected to see this happen: successful compilation

Instead, this happened: compile error:

error: lifetime may not live long enough
  --> src/main.rs:14:23
   |
12 | impl<'a, 'b> Context<'a, 'b> {
   |      --  -- lifetime `'b` defined here
   |      |
   |      lifetime `'a` defined here
13 |     fn find(&mut self) -> &mut Item<'a> {
14 |         let mut res = &mut self.root;
   |                       ^^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a`
   |
   = help: consider adding the following bound: `'b: 'a`
   = note: requirement occurs because of a mutable reference to `Item<'_>`
   = note: mutable references are invariant over their type parameter
   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance

The error is very unclear on what the actually problem is. It also doesn't seem an actual problem, since root doesn't mention 'b at all and intuitively it should work.

The following version works, which lets me guess it's some lifetime coercion issue:

fn explicit_get_mut<'a, 'c>(
    items: &'c mut HashMap<&str, Item<'a>>,
    seg: &str,
) -> &'c mut Item<'a> {
    items.get_mut(seg).unwrap()
}

fn find2(&mut self) -> &mut Item<'a> {
    let mut res: &mut Item<'a> = &mut self.root;
    for seg in &self.path {
        res = explicit_get_mut(&mut res.items, seg);
    }
    res
}
Meta

rustc --version --verbose:

rustc 1.89.0-nightly (99e7c15e8 2025-06-01)
binary: rustc
commit-hash: 99e7c15e81385b38a8186b51edc4577d5d7b5bdd
commit-date: 2025-06-01
host: x86_64-unknown-linux-gnu
release: 1.89.0-nightly
LLVM version: 20.1.5

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 reproducing the minimized example in src/main.rs with the reported rustc 1.89.0-nightly toolchain, then compare the diagnostic with the working explicit_get_mut version. Investigate the lifetime error and variance explanation; done means the reported behavior or diagnostic is clarified and covered by an appropriate compiler test, if the issue is confirmed.

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
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.