How to use the Rustonomicon's way to interpret this returned lifetime issue
⚓ Rust 📅 2025-08-01 👤 surdeus 👁️ 11Consider this example:
use std::collections::HashMap;
fn get_default2<'r>(map: &'r mut HashMap<i32, ()>, key: i32) -> &'r mut () {
if map.contains_key(&key) {
// ^~~~~~~~~~~~~~~~~~ 'n
return match map.get_mut(&key) { // #1
// + 'r
Some(value) => value, // |
None => unreachable!(), // |
}; // v
}
// At this point, `map.get_mut` was never
// called! (As opposed to having been called,
// but its result no longer being in use.)
// #2
map.insert(key, ()); // OK now.
map.get_mut(&key).unwrap()
}
This code is sourced from 2094-nll - The Rust RFC Book. From the perspective of NLL, the example is ok because the Control-flow graph that goes through #1 won't go through #2, so the loan at #1 does not include the point #2.
However, I don't know how to interpret this example in terms of the Rustonomicon's way. I tried to annotate the example in Rustonomicon's manner:
fn get_default2<'r>(map: &'r mut HashMap<i32, ()>, key: i32) -> &'r mut () {
'body:{
if 't:{ map.contains_key(&'t key) } {
return match map.get_mut(&'r key) { // #1
Some(value) => value,
None => unreachable!(),
};
}
// #2
map.insert(key, ()); // OK now.
map.get_mut(&key).unwrap()
}
}
/*
'r:{
get_default2(&'r map,0);
}
*/
The lifetime 'r contains the function call, so the whole 'body is contained within 'r, so the borrowing borrowed at #1 should be alive at #2, which should conflict with the borrowing at #2.
Out-of-curiously, I wonder how to use the Rustonomicon's mental model to interpret this tricky problem.
4 posts - 3 participants
🏷️ Rust_feed