Open
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