Cannot borrow immutable borrowed content as mutable - rust

I'm trying to develop a message routing app. I've read the official Rust docs and some articles and thought that I got how pointers, owning, and borrowing stuff works but realized that I didn't.
use std::collections::HashMap;
use std::vec::Vec;
struct Component {
address: &'static str,
available_workers: i32,
lang: i32
}
struct Components {
data: HashMap<i32, Vec<Component>>
}
impl Components {
fn new() -> Components {
Components {data: HashMap::new() }
}
fn addOrUpdate(&mut self, component: Component) -> &Components {
if !self.data.contains_key(&component.lang) {
self.data.insert(component.lang, vec![component]);
} else {
let mut q = self.data.get(&component.lang); // this extra line is required because of the error: borrowed value does not live long enough
let mut queue = q.as_mut().unwrap();
queue.remove(0);
queue.push(component);
}
self
}
}
(Also available on the playground)
Produces the error:
error: cannot borrow immutable borrowed content `**queue` as mutable
--> src/main.rs:26:13
|
26 | queue.remove(0);
| ^^^^^ cannot borrow as mutable
error: cannot borrow immutable borrowed content `**queue` as mutable
--> src/main.rs:27:13
|
27 | queue.push(component);
| ^^^^^ cannot borrow as mutable
Could you please explain the error and it would be great if you can give me the right implementation.

Here is an MCVE of your problem:
use std::collections::HashMap;
struct Components {
data: HashMap<u8, Vec<u8>>,
}
impl Components {
fn add_or_update(&mut self, component: u8) {
let mut q = self.data.get(&component);
let mut queue = q.as_mut().unwrap();
queue.remove(0);
}
}
Before NLL
error[E0596]: cannot borrow immutable borrowed content `**queue` as mutable
--> src/lib.rs:11:9
|
11 | queue.remove(0);
| ^^^^^ cannot borrow as mutable
After NLL
error[E0596]: cannot borrow `**queue` as mutable, as it is behind a `&` reference
--> src/lib.rs:11:9
|
11 | queue.remove(0);
| ^^^^^ cannot borrow as mutable
Many times, when something seems surprising like this, it's useful to print out the types involved. Let's print out the type of queue:
let mut queue: () = q.as_mut().unwrap();
error[E0308]: mismatched types
--> src/lib.rs:10:29
|
10 | let mut queue: () = q.as_mut().unwrap();
| ^^^^^^^^^^^^^^^^^^^ expected (), found mutable reference
|
= note: expected type `()`
found type `&mut &std::vec::Vec<u8>`
We have a mutable reference to an immutable reference to a Vec<u8>. Because we have an immutable reference to the Vec, we cannot modify it! Changing self.data.get to self.data.get_mut changes the type to &mut &mut collections::vec::Vec<u8> and the code compiles.
If you want to implement the concept of "insert or update", you should check into the entry API, which is more efficient and concise.
Beyond that, Rust uses snake_case for method naming, not camelCase.

Related

How do I get the length of a Vec after it has been modified?

I have a function which takes a Vec and pushes zero or more elements to it. The Vec and the reference passed to the function are both mut. When I try to get the length of the Vec upon return (to see how many elements were pushed), I get the dreaded "cannot borrow 'foo' as immutable because it is also borrowed as mutable" error.
In general, I get why this error exists in general. I don't get why it's necessary here.
Surely there's a way to do this -- I can't be the first person who has tried something like this.
Here's a stripped-down version of what I'm trying to do, that replicates the error.
fn main() {
let mut stack = vec!["one"];
push(&mut stack, "two");
}
fn push<'a>(stack: &'a mut Vec<&'a str>, value: &'a str) {
stack.push(value);
}
#[test]
fn test_len() {
let mut stack = vec!["one"];
push(&mut stack, "two");
assert_eq!(stack.len(), 2);
}
error[E0502]: cannot borrow `stack` as immutable because it is also borrowed as mutable
--> src/main.rs:14:16
|
13 | push(&mut stack, "two");
| ---------- mutable borrow occurs here
14 | assert_eq!(stack.len(), 2);
| ^^^^^^^^^^^
| |
| immutable borrow occurs here
| mutable borrow later used here
Don't force the references lifetime and the lifetime of the mutable borrow to be the same.
fn push<'a>(stack: &mut Vec<&'a str>, value: &'a str) {
stack.push(value);
}

Implementing a recursive cache in Rust [duplicate]

This question already has answers here:
Returning a reference from a HashMap or Vec causes a borrow to last beyond the scope it's in?
(1 answer)
When is it necessary to circumvent Rust's borrow checker?
(1 answer)
Closed 1 year ago.
use std::collections::HashMap;
#[derive(Clone, Hash, Eq, PartialEq)]
struct HeavyCloneKey;
struct Map<V> {
map : HashMap<HeavyCloneKey, V>
}
impl<V> Map<V> {
pub fn get_mut(&mut self, key: &HeavyCloneKey) -> Option<&mut V> {
if let Some(v) = self.map.get_mut(key) {
return Some(v);
}
// some logic to decide if create a new value;
if self.map.len() > 64 {
None
} else {
let v = create_v_with_long_code();
let v = self.map.entry(key.clone()).or_insert_with(|| v);
Some(v)
}
}
}
fn create_v_with_long_code<V>() -> V {
unimplemented!()
}
fn main() {
}
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=19c45ebfb1a39271ff5bd2443399596a
I can't understand why this can't work:
error[E0502]: cannot borrow `self.map` as immutable because it is also borrowed as mutable
--> src/main.rs:18:12
|
12 | pub fn get_mut(&mut self, key: &HeavyCloneKey) -> Option<&mut V> {
| - let's call the lifetime of this reference `'1`
13 | if let Some(v) = self.map.get_mut(key) {
| -------- mutable borrow occurs here
14 | return Some(v);
| ------- returning this value requires that `self.map` is borrowed for `'1`
...
18 | if self.map.len() > 64 {
| ^^^^^^^^ immutable borrow occurs here
These two borrows won't appear at the same time, what's the problem? How can I do this?
Although the code can be compiled by using contains_key before get_mut, it pays more overhead;
It helps a little to desugar the lifetimes by providing your own annotations on the references. It doesn't really matter here though as lifetimes aren't actually the issue.
pub fn get_mut<'s, 'k>(&'s mut self, key: &'k HeavyCloneKey) -> Option<&'s mut V> {
This gets us a little better error message:
error[E0502]: cannot borrow `self.map` as immutable because it is also borrowed as mutable
--> src/main.rs:18:12
|
12 | pub fn get_mut<'s, 'k>(&'s mut self, key: &'k HeavyCloneKey) -> Option<&'s mut V> {
| -- lifetime `'s` defined here
13 | if let Some(v) = self.map.get_mut(key) {
| -------- mutable borrow occurs here
14 | return Some(v);
| ------- returning this value requires that `self.map` is borrowed for `'s`
...
18 | if self.map.len() > 64 {
| ^^^^^^^^ immutable borrow occurs here
error[E0499]: cannot borrow `self.map` as mutable more than once at a time
--> src/main.rs:22:21
|
12 | pub fn get_mut<'s, 'k>(&'s mut self, key: &'k HeavyCloneKey) -> Option<&'s mut V> {
| -- lifetime `'s` defined here
13 | if let Some(v) = self.map.get_mut(key) {
| -------- first mutable borrow occurs here
14 | return Some(v);
| ------- returning this value requires that `self.map` is borrowed for `'s`
...
22 | let v = self.map.entry(key.clone()).or_insert_with(|| v);
| ^^^^^^^^ second mutable borrow occurs here
We have two errors here. Both stem from the rust compiler not being able to tell that we don't use the mutable borrow from line 13 later in the function.
The first says "you grabbed a mutable reference to self here so we can't let you have an immutable reference there". The second says "you grabbed a mutable reference to self here so we can't let you have a second mutable reference there".
How do we fix this? By making it clearer to the compiler that we'll never hold that first mutable reference. We can do this by manually checking if that key exists first. Change this
if let Some(v) = self.map.get_mut(key) {
return Some(v);
}
to this
if self.map.contains_key(key) {
return self.map.get_mut(key);
}
and it will compile.

Why is a struct field borrowed longer than expected

Consider the following program. Each element should hold references to elements in the container that already existed at the time it was added.
struct Element<'a> {
previous: Vec<&'a Element<'a>>,
}
struct Container<'a> {
elements: Vec<Element<'a>>,
}
impl <'a>Container<'a> {
fn new() -> Container<'a> {
Container{elements: Vec::new()}
}
fn add(&'a mut self) -> &'a Element {
let previous = self.elements.iter().collect();
let element = Element{previous: previous};
self.elements.push(element);
&self.elements[self.elements.len() - 1]
}
}
fn main() {
let mut _c = Container::new();
}
This fails with the error
error[E0502]: cannot borrow `self.elements` as mutable because it is also borrowed as immutable
--> nested.rs:17:9
|
9 | impl <'a>Container<'a> {
| -- lifetime `'a` defined here
...
15 | let previous = self.elements.iter().collect();
| --------------------
| |
| immutable borrow occurs here
| argument requires that `self.elements` is borrowed for `'a`
16 | let element = Element{previous: previous};
17 | self.elements.push(element);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
error: aborting due to previous error
For more information about this error, try `rustc --explain E0502`.
But why is self.elements borrowed for 'a? I would expect it would no longer be borrowed after the collect() is done. I'd expect that each element that was in self.elements would be borrowed immutably because of their references now stored in element.previous. But self.elements should be free to be mutated now.
The error is : cannot borrow self.elements as mutable because it is also borrowed as immutable
// this is borrow self.selements
let previous:Vec<&Element> = self.elements.iter().collect();
previous is borrow from self.elements as immutable,
self.elements.push(element); use self.elements as mutable, you can't use mutable and immutable both

How to implement generic intersperse with mutations possible

Goal
Create function/macro which has an api like such:
fn writesperse(
buf: &mut String,
items: impl IntoIterator<Item=impl fmt::Display>,
sep: impl fmt::Display,
) -> fmt::Result {
// intersperse impl elided
}
with the main consumer of this api being a struct similar to:
use std::fmt;
// Drives building of query
struct QueryBuilder<'a> {
buf: String,
data: &'a Data,
state: State,
}
impl<'a> QueryBuilder<'a> {
// example method showing how writesperse might be used
fn f(&mut self) -> fmt::Result {
writesperse(
&mut self.buf,
self.data.names().map(|n| self.state.resolve(n)),
", ",
)
}
}
// Represents mutable container for computed values
struct State;
impl State {
fn resolve(&mut self, _name: &str) -> &StateRef {
// mutate state if name has not been seen before (elided)
&StateRef
}
}
// Represents example computed value
struct StateRef;
impl fmt::Display for StateRef {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "STATEREF")
}
}
// Immutable container with various collections of objects
struct Data;
impl Data {
// example iterator of references to some owned data
fn names(&self) -> impl Iterator<Item=&str> {
::std::iter::once("name")
}
// another iterator of a different references
fn items(&self) -> impl Iterator<Item=&DataRef> {
::std::iter::once(&DataRef)
}
}
// Represents some type Data might own
struct DataRef;
Error
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/lib.rs:13:50
|
13 | self.data.names().map(|n| self.state.resolve(n)),
| ^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime '_ as defined on the body at 13:35...
--> src/lib.rs:13:35
|
13 | self.data.names().map(|n| self.state.resolve(n)),
| ^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/lib.rs:13:39
|
13 | self.data.names().map(|n| self.state.resolve(n)),
| ^^^^^^^^^^
note: but, the lifetime must be valid for the method call at 13:13...
--> src/lib.rs:13:13
|
13 | self.data.names().map(|n| self.state.resolve(n)),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that a type/lifetime parameter is in scope here
--> src/lib.rs:13:13
|
13 | self.data.names().map(|n| self.state.resolve(n)),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
What I've tried
My only success thus far has been to manually do the intersperse logic at each site where it is needed.
let mut iter = some_iter.into_iter();
if let Some(i) = iter.next() {
// do any state mutation here so mutable reference is released
let n = self.state.resolve(n);
write!(&mut self.buf, "{}", n)?;
}
for i in iter {
// do same thing above
}
If I try and make State::resolve immutable, (which means I would need to pre-compute the values which is not desirable), I get a different error.
error[E0502]: cannot borrow `self` as immutable because it is also borrowed as mutable
--> src/lib.rs:13:35
|
11 | writesperse(
| ----------- mutable borrow later used by call
12 | &mut self.buf,
| ------------- mutable borrow occurs here
13 | self.data.names().map(|n| self.state.resolve(n)),
| ^^^ ---- second borrow occurs due to use of `self` in closure
| |
| immutable borrow occurs here
This error is easier to understand. However, I don't understand why what I am trying to do is disallowed. Why can I not hand out a mutable reference to QueryBuilder's buf and an iterator of references to objects within State and/or Data at the same time?
Ultimately, my number one priority is abstracting the intersperse logic into some function or macro which expects an Iterator<Item=fmt::Display>. It would be an added bonus if this Iterator could possibly mutate state and return a reference to its data. I don't think this is possible though, at least from my understanding of the streaming-iterator crate.
Thanks for your help!
writesperse is not the problem here, resolve is.
Because it takes &mut self and returns a reference with a lifetime bound to self, you can't call resolve a second time unless the reference obtained from the first call has been dropped. You can see this in this simplified f (compiler error interspersed):
// error[E0499]: cannot borrow `self.state` as mutable more than once at a time
fn f(&mut self) {
let a = self.state.resolve("alec");
// ---------- first mutable borrow occurs here
let _b = self.state.resolve("brian");
// ^^^^^^^^^^ second mutable borrow occurs here
println!("{}", a);
// - first borrow later used here
}
Part of the contract of an Iterator is that it does not yield internal references. So |n| self.state.resolve(n) is simply not a closure that can be passed to Iterator::map.
Fixing resolve
If resolve took &self instead of &mut self, this would work because the closure would not need to borrow self.state exclusively; it could return references with the lifetime of the original without worrying about overlap. So let's try that:
fn resolve(&self, _name: &str) -> &StateRef {
// some kind of interior mutability thing here, probably have to return
// `std::cell:Ref<StateRef>` or `MutexGuard<StateRef>` instead, but that
// doesn't matter for this demonstration
&StateRef
}
Oh dear.
error[E0502]: cannot borrow `self` as immutable because it is also borrowed as mutable
--> src/lib.rs:23:35
|
21 | writesperse(
| ----------- mutable borrow later used by call
22 | &mut self.buf,
| ------------- mutable borrow occurs here
23 | self.data.names().map(|n| self.state.resolve(n)),
| ^^^ ---- second borrow occurs due to use of `self` in closure
| |
| immutable borrow occurs here
What's going on? Because the closure uses self in a context where an immutable reference is required, the closure borrows self, and the &mut self.buf also borrows (part of) self mutably, and they both have to exist at the same time to pass into writesperse. So this looks like a dead end, but it's actually really close: it just needs a small change to f to compile.
fn f(&mut self) -> fmt::Result {
let state = &self.state;
writesperse(
&mut self.buf,
self.data.names().map(|n| state.resolve(n)),
", ",
)
}
The compiler can reason about mutually exclusive partial borrows as long as they happen all within the body of a single function. The compiler will let you borrow self.state and mutably borrow self.buf at the same time as long as the borrows happen in the same function. Creating a variable to borrow self.state makes it so that only state is captured by the closure, not self.
Other options
The above works, if you're able to make resolve take &self. Here are some other ideas:
You could attack the problem from the other direction: make resolve return StateRef by value so it doesn't extend the &mut borrow.
You can achieve the same thing by altering the closure so that it doesn't return a reference; |n| state.resolve(n).to_string() works with no further changes (but it does do a bunch of unnecessary allocation and copying).
You could use Arc or Rc instead of & references and defer all lifetime management to runtime.
You could write a macro that does the repetitive part for you so that writesperse is not necessary.
See also
How do I return a reference to something inside a RefCell without breaking encapsulation? if you need to use interior mutability to make resolve take &self
Mutable borrow of self doesn't change to immutable explains why state is still considered "mutably borrowed" after resolve returns

Passing the contents of a RefCell<&mut T> to a function

Calling methods on a borrowed RefCell<&mut T> (That is, a Ref<&mut T>) works as expected, but I can't seem to pass it to a function. Consider the following code:
use std::cell::RefCell;
fn main() {
let mut nums = vec![1, 2, 3];
foo(&mut nums);
println!("{:?}", nums);
}
fn foo(nums: &mut Vec<usize>) {
let num_cell = RefCell::new(nums);
num_cell.borrow_mut().push(4);
push_5(*num_cell.borrow_mut());
}
fn push_5(nums: &mut Vec<usize>) {
nums.push(4);
}
num_cell.borrow_mut().push(4) works, but push_5(*num_cell.borrow_mut()) errors with:
error[E0389]: cannot borrow data mutably in a `&` reference
--> src/main.rs:14:12
|
14 | push_5(*num_cell.borrow_mut());
| ^^^^^^^^^^^^^^^^^^^^^^ assignment into an immutable reference
After dereferencing the Ref, I expected to get the mutable reference inside so the error doesn't really make sense to me. What gives?
push_5(*num_cell.borrow_mut());
Remove the * and the compiler suggests
error[E0308]: mismatched types
--> src/main.rs:14:12
|
14 | push_5(num_cell.borrow_mut());
| ^^^^^^^^^^^^^^^^^^^^^
| |
| expected mutable reference, found struct `std::cell::RefMut`
| help: consider mutably borrowing here: `&mut num_cell.borrow_mut()`
|
= note: expected type `&mut std::vec::Vec<usize>`
found type `std::cell::RefMut<'_, &mut std::vec::Vec<usize>>`
push_5(&mut num_cell.borrow_mut()); compiles.
push_5(num_cell.borrow_mut().as_mut()); does too

Resources