Info
This post is auto-generated from RSS feed The Rust Programming Language Forum - Latest topics. Source: Yet another fight with the borrow checker
I ran into (almost exactly) the 1st problem in this article: Four limitations of Rustโs borrow checker | Considerations on Codecrafting
let's reiterate the problem in this simple example:
use std::collections::HashMap;
struct Cache(HashMap<u32, String>);
impl Cache {
fn get(&mut self, k: &u32) -> &String {
if let Some(v) = self.0.get(k) {
return v;
}
self.0.insert(*k, k.to_string());
self.0.get(k).unwrap()
}
}
see it in Rust Playground
it won't compile:
error[E0502]: cannot borrow `self.0` as mutable because it is also borrowed as immutable
--> src/main.rs:10:9
|
6 | fn get(&mut self, k: &u32) -> &String {
| - let's call the lifetime of this reference `'1`
7 | if let Some(v) = self.0.get(k) {
| ------ immutable borrow occurs here
8 | return v;
| - returning this value requires that `self.0` is borrowed for `'1`
9 | }
10 | self.0.insert(*k, k.to_string());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
For more information about this error, try `rustc --explain E0502`.
clearly borrow checker is at fault here, that's a known fact.
I know refactoring it using HashMap::entry works, like this:
use std::collections::HashMap;
struct Cache(HashMap<u32, String>);
impl Cache {
fn get(&mut self, k: &u32) -> &String {
self.0.entry(*k).or_insert_with(|| k.to_string() )
}
}
see it in Rust Playground
In a way, this is better since it only performs one lookup.
But it's not very flexible, what if I want something a little more complex? like I want to check if a fallback entry exist:
use std::collections::HashMap;
struct Cache(HashMap<u32, String>);
impl Cache {
fn get(&mut self, k: &u32) -> &String {
if let Some(v) = self.0.get(k) {
return v;
}
if let Some(v) = self.0.get(&(*k + 42)) {
return v;
}
self.0.insert(*k, k.to_string());
self.0.get(k).unwrap()
}
}
fn main() { }
I don't see a way to fix this cleanly.
Another grunt I have is that .entry()
wants an owned key, it would be better if it could take a borrow and only calls .to_owned()
when required.
1 post - 1 participant
๐ท๏ธ rust_feed