Ahem, I am seeing a borrow-checker error which I don't entirely understand:
struct Holder {
inner: String,
}
impl Holder {
fn weird(&mut self) -> &str {
self.inner = "hello".to_string();
&self.inner
}
}
fn f(mut h: Holder) {
let s1 = h.weird();
let s2 = h.inner.as_str();
println!("{} {}", s1, s2)
}
The key here is fn weird(&mut self) -> &str
-- it takes a &mut
reference in, and emits a &
reference. But it seems that it is essentially treated as fn weird(&mut self) -> &mut str
by the borrow checker -- in the f
, the h
remains frozen after call to weird
, so accessing it, even via &
, is impossible.
Two questions:
Is this a limitation of a borrow checker, or is the problem fundamental? To me, it seems like the above code should work, regardless of what's happening inside weird
. What does the stacked borrows model say about this code?
What are the practical work-arounds here? In the actual problem, the weird
inserts a key/value into a map and returns a shared reference to the value:
let mut hm = HashMap::new();
hm.insert(1, "hello".to_string());
let w = &*hm.entry(2).or_insert("world".to_string());
let h = &hm[&1];
println!("{} {}", h, w);
I can work-around that by doing a second lookup, but that's not elegant:
let mut hm = HashMap::new();
hm.insert(1, "hello".to_string());
hm.entry(2).or_insert("world".to_string());
let w = &hm[&2];
let h = &hm[&1];
println!("{} {}", h, w);