{
"$type": "site.standard.document",
"bskyPostRef": {
"cid": "bafyreigvj34ck7wvcim4mdfhd4qhmcxlqdsqil2zi4gmqamzlwfljapmdq",
"uri": "at://did:plc:ivbknywyskln22er3nkssdhl/app.bsky.feed.post/3meqbhrgro7t2"
},
"path": "/t/get-mut-map-back-from-entry-api/24003#post_1",
"publishedAt": "2026-02-13T09:15:22.000Z",
"site": "https://internals.rust-lang.org",
"textContent": "Consider the following API:\n\n\n use std::collections::HashMap;\n use std::hash::Hash;\n\n pub fn get_priority_mut<'a, K, V>(\n map: &'a mut HashMap<K, V>,\n key1: &K,\n key2: &K,\n ) -> Option<&'a mut V>\n where\n K: Eq + Hash,\n {\n // Check for the first key without mutably borrowing the map\n if map.contains_key(key1) {\n map.get_mut(key1)\n } else {\n // If the first isn't there, we are free to mutably borrow for the second\n map.get_mut(key2)\n }\n }\n\n\nI would like to avoid the double-lookup of `key1`, but we can't because of the usual borrow checker limitation. The usual fix for that is to use entry api, but even that doesn't work in this case:\n\n\n use std::collections::HashMap;\n use std::collections::hash_map::Entry;\n use std::hash::Hash;\n\n // ❌ THIS WILL NOT COMPILE\n pub fn get_priority_mut_entry<'a, K, V>(\n map: &'a mut HashMap<K, V>,\n key1: K,\n key2: K,\n ) -> Option<&'a mut V>\n where\n K: Eq + Hash,\n {\n match map.entry(key1) {\n Entry::Occupied(occupied) => Some(occupied.into_mut()),\n Entry::Vacant(_vacant) => {\n match map.entry(key2) {\n Entry::Occupied(occupied2) => Some(occupied2.into_mut()),\n Entry::Vacant(_) => None,\n }\n }\n }\n }\n\n\n\n error[E0499]: cannot borrow `*map` as mutable more than once at a time\n --> src/lib.rs:17:19\n |\n 6 | pub fn get_priority_mut_entry<'a, K, V>(\n | -- lifetime `'a` defined here\n ...\n 14 | match map.entry(key1) {\n | --- first mutable borrow occurs here\n 15 | Entry::Occupied(occupied) => Some(occupied.into_mut()),\n | ------------------------- returning this value requires that `*map` is borrowed for `'a`\n 16 | Entry::Vacant(_vacant) => {\n 17 | match map.entry(key2) {\n | ^^^ second mutable borrow occurs here\n\n\nI'd like to propose a potential solution: Add a method to `[Vacant|Occupied]Entry` that consumes the entry and returns `&mut HashMap`. If you had this API, you could write this:\n\n\n match map.entry(key1) {\n Entry::Occupied(occupied) => Some(occupied.into_mut()),\n Entry::Vacant(vacant) => {\n match vacant.into_map().entry(key2) {\n Entry::Occupied(occupied2) => Some(occupied2.into_mut()),\n Entry::Vacant(_) => None,\n }\n }\n }\n\n\nwhich does not run into the borrow checker limitation.",
"title": "Get `&mut Map` back from entry API"
}