immutable variable where a mutable variable seems to be provided [duplicate] - rust

This question already has answers here:
Cannot borrow immutable borrowed content as mutable when implementing a binary tree with Rc
(1 answer)
Cannot borrow immutable borrowed content as mutable
(1 answer)
Closed 4 years ago.
I have a clonable struct, called GenICam. This struct has a HashMap of Rc<dyn Node> trait objects, and a HashMap of Rc<Category> structs which implement the Node trait. The keys are NodeName which is an alias type for String.
Each category has a list of feature names, which are represented in the nodes HashMap of GenICam. This list should be used to populate the node_list field with references to the nodes using the functions below:
use std::{collections::HashMap, rc::Rc};
type NodeName = String;
#[derive(Clone)]
pub struct GenICam {
nodes: HashMap<NodeName, Rc<Node>>,
categories: HashMap<NodeName, Rc<Category>>,
}
impl GenICam {
fn get_categories(&self) -> Vec<Rc<Category>> {
let mut collect = Vec::new();
for i in &self.categories {
collect.push(i.1.clone());
}
collect
}
/// Fills all categories with references to the features if available
fn populate_categories(&mut self) {
let mut cats = self.get_categories();
for cat in cats {
let mut mutcat = cat;
mutcat.populate(&self);
}
}
}
#[derive(Clone)]
pub struct Category {
pub name: NodeName,
features: Vec<String>,
pub node_list: HashMap<NodeName, Rc<Node>>,
}
impl Category {
pub fn populate(&mut self, genicam: &GenICam) {
for feat in &self.clone().features {
let result = genicam.node(feat.to_string());
match result {
None => (),
Some(x) => self.add_to_node_list(x),
};
}
}
/// populate the node hashmap with the given node
pub fn add_to_node_list(&mut self, node: &Rc<Node>) {
println!("Succes: {:?}", node.name());
self.node_list.insert(node.name(), node.clone());
}
}
I get the following error:
error[E0596]: cannot borrow immutable borrowed content as mutable
--> src/genicam.rs:174:4
|
| mutcat.populate(&self);
| ^^^^^^ cannot borrow as mutable
I cannot wrap my head around why mutcat is immutable, since it is defined as let mut.

Related

Multiple mutable borrows when using result of a method call [duplicate]

This question already has answers here:
Why can't I store a value and a reference to that value in the same struct?
(4 answers)
Closed 2 years ago.
In this simplified code, I have two important structs: Owner takes ownership of an object, adds it to a Vec, and returns a reference to it; RefKeeper just holds references to objects in a Vec. Owner also has a RefKeeper.
struct Foo(i32);
struct Owner<'o> {
list: Vec<Foo>,
refkeeper: RefKeeper<'o>,
}
impl<'o> Owner<'o> {
pub fn new() -> Self {
Self {
list: Vec::new(),
refkeeper: RefKeeper::new(),
}
}
pub fn add(&mut self, me: Foo) -> &Foo {
self.list.push(me);
return self.list.last().unwrap();
}
pub fn add_ref(&mut self, me: &'o Foo) {
self.refkeeper.add(me);
}
}
struct RefKeeper<'ro> {
list: Vec<&'ro Foo>,
}
impl<'ro> RefKeeper<'ro> {
pub fn new() -> Self {
Self { list: Vec::new() }
}
pub fn add(&mut self, me: &'ro Foo) {
self.list.push(me);
}
}
fn main() {
let mut owner = Owner::new();
let a1 = Foo(1);
let a1_ref = owner.add(a1);
// this variant doesn't work
owner.add_ref(a1_ref);
// let mut refkeeper = RefKeeper::new();
// refkeeper.add(a1_ref);
// let a2 = Foo(2);
// owner.add_ref(&a2);
}
Two variants work: if I make RefKeeper externally, I can store the ref returned by Owner::add; on the other hand, if I make a new object (a2), I can store &a2 in owner.refkeeper with no problem. Why does the other variant give me this error?
error[E0499]: cannot borrow `owner` as mutable more than once at a time
--> src/main.rs:46:5
|
43 | let a1_ref = owner.add(a1);
| ----- first mutable borrow occurs here
...
46 | owner.add_ref(a1_ref);
| ^^^^^ ------ first borrow later used here
| |
| second mutable borrow occurs here
Is there something fundamentally wrong with this pattern? I'm under the impression that there should be no issue with lifetimes because all the borrows are being used in the same object.
Its because Owner::add returns a reference that is bound to the lifetime of &mut self. So as long as the return value exists (a1_ref) then the &mut self reference does too. So calling add_ref fails because it requires another mut self reference of that same instance.
You can either have one mutable reference, or many immutable references.
The reason calling refkeeper.add and then owner.add_ref is not giving you the same issue is because adding to refkeeper does not require another reference to owner.
You might want to look at std::rc::Rc.

Can an element of a RefCell<Vec<_>> stored in a struct modify values of another element in the same Vec?

I have a struct containing a vector whose elements must be able to modify other elements in the vector.
I tried doing it like this:
use core::cell::RefCell;
struct Go {
car: i32,
}
impl Go {
pub fn attack(&mut self, val: &mut Self) {
val.car = self.car;
self.car = 5;
}
}
struct World {
pub params: RefCell<Vec<Go>>,
pub val: i32,
}
fn main() {
let world = World {
params: RefCell::new(vec![]),
val: 42,
};
for m in 0..10 {
world.params.borrow_mut().push(Go { car: m });
}
world.params.borrow()[5].attack(&mut world.params.borrow()[6]);
}
playground
However , I got these errors
error[E0596]: cannot borrow data in a dereference of `std::cell::Ref<'_, std::vec::Vec<Go>>` as mutable
--> src/main.rs:29:5
|
29 | world.params.borrow()[5].attack(&mut world.params.borrow()[6]);
| ^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::cell::Ref<'_, std::vec::Vec<Go>>`
error[E0596]: cannot borrow data in a dereference of `std::cell::Ref<'_, std::vec::Vec<Go>>` as mutable
--> src/main.rs:29:42
|
29 | world.params.borrow()[5].attack(&mut world.params.borrow()[6]);
| ^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::cell::Ref<'_, std::vec::Vec<Go>>`
How do I get this done?
also please note that Due to some constraints , I do not want to create any extra variables in the main function.
The attack function works like an update function for different elements of the vec in the main program I am supposed to be running

How do I enforce immutability for public views of reference-counted types with interior mutability? [duplicate]

I have a struct that has inner mutability.
use std::cell::RefCell;
struct MutableInterior {
hide_me: i32,
vec: Vec<i32>,
}
struct Foo {
//although not used in this particular snippet,
//the motivating problem uses interior mutability
//via RefCell.
interior: RefCell<MutableInterior>,
}
impl Foo {
pub fn get_items(&self) -> &Vec<i32> {
&self.interior.borrow().vec
}
}
fn main() {
let f = Foo {
interior: RefCell::new(MutableInterior {
vec: Vec::new(),
hide_me: 2,
}),
};
let borrowed_f = &f;
let items = borrowed_f.get_items();
}
Produces the error:
error[E0597]: borrowed value does not live long enough
--> src/main.rs:16:10
|
16 | &self.interior.borrow().vec
| ^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
17 | }
| - temporary value only lives until here
|
note: borrowed value must be valid for the anonymous lifetime #1 defined on the method body at 15:5...
--> src/main.rs:15:5
|
15 | / pub fn get_items(&self) -> &Vec<i32> {
16 | | &self.interior.borrow().vec
17 | | }
| |_____^
The problem is that I can't have a function on Foo that returns a borrowed vec, because the borrowed vec is only valid for the lifetime of the Ref, but the Ref goes out of scope immediately.
I think the Ref must stick around because:
RefCell<T> uses Rust's lifetimes to implement 'dynamic borrowing', a process whereby one can claim temporary, exclusive, mutable access to the inner value. Borrows for RefCell<T>s are tracked 'at runtime', unlike Rust's native reference types which are entirely tracked statically, at compile time. Because RefCell<T> borrows are dynamic it is possible to attempt to borrow a value that is already mutably borrowed; when this happens it results in task panic.
Now I could instead write a function like this that returns the entire interior:
pub fn get_mutable_interior(&self) -> std::cell::Ref<MutableInterior>;
However this potentially exposes fields (MutableInterior.hide_me in this example) that are really private implementation details to Foo.
Ideally I just want to expose the vec itself, potentially with a guard to implement the dynamic borrowing behavior. Then callers do not have to find out about hide_me.
Instead of creating a brand new type, you can use Ref::map (since Rust 1.8). This has the same result as Levans' existing answer:
use std::cell::Ref;
impl Foo {
pub fn get_items(&self) -> Ref<'_, Vec<i32>> {
Ref::map(self.interior.borrow(), |mi| &mi.vec)
}
}
You can also use new features like impl Trait to hide the Ref from the API:
use std::cell::Ref;
use std::ops::Deref;
impl Foo {
pub fn get_items(&self) -> impl Deref<Target = Vec<i32>> + '_ {
Ref::map(self.interior.borrow(), |mi| &mi.vec)
}
}
You can create a new struct similar to the Ref<'a,T> guard returned by RefCell::borrow(), in order to wrap this Ref and avoid having it going out of scope, like this:
use std::cell::Ref;
struct FooGuard<'a> {
guard: Ref<'a, MutableInterior>,
}
then, you can implement the Deref trait for it, so that it can be used as if it was a &Vec<i32>:
use std::ops::Deref;
impl<'b> Deref for FooGuard<'b> {
type Target = Vec<i32>;
fn deref(&self) -> &Vec<i32> {
&self.guard.vec
}
}
after that, update your get_items() method to return a FooGuard instance:
impl Foo {
pub fn get_items(&self) -> FooGuard {
FooGuard {
guard: self.interior.borrow(),
}
}
}
and Deref does the magic:
fn main() {
let f = Foo {
interior: RefCell::new(MutableInterior {
vec: Vec::new(),
hide_me: 2,
}),
};
let borrowed_f = &f;
let items = borrowed_f.get_items();
let v: &Vec<i32> = &items;
}
You can wrap the Vec in an Rc.
use std::cell::RefCell;
use std::rc::Rc;
struct MutableInterior {
hide_me: i32,
vec: Rc<Vec<i32>>,
}
struct Foo {
interior: RefCell<MutableInterior>,
}
impl Foo {
pub fn get_items(&self) -> Rc<Vec<i32>> {
self.interior.borrow().vec.clone() // clones the Rc, not the Vec
}
}
fn main() {
let f = Foo {
interior: RefCell::new(MutableInterior {
vec: Rc::new(Vec::new()),
hide_me: 2,
}),
};
let borrowed_f = &f;
let items = borrowed_f.get_items();
}
When you need to mutate the Vec, use Rc::make_mut to obtain a mutable reference to the Vec. If there are still other Rcs referring to the Vec, make_mut will dissociate the Rc from the other Rcs, clone the Vec and update itself to refer to that new Vec, then give you a mutable reference to it. This ensures that the value in the other Rcs doesn't suddenly change (because Rc by itself doesn't provide interior mutability).

Lifetime on trait returning iterator

I'm working with a trait requiring a function returning an iterator without consuming the object. The iterator itself returns copies of data values, not references. As the iterator implementation requires a reference to the object it is iterating over, I end up having to declare lots of lifetimes (more than I would have thought necessary, but could not get it to compile otherwise). I then run into trouble with borrow duration - a minimal "working" example is as follows:
pub trait MyTrait<'a> {
type IteratorType: Iterator<Item=u32>;
fn iter(&'a self) -> Self::IteratorType;
fn touch(&'a mut self, value: u32);
}
struct MyStruct {
data: Vec<u32>
}
struct MyIterator<'a> {
structref: &'a MyStruct,
next: usize,
}
impl<'a> Iterator for MyIterator<'a> {
type Item = u32;
fn next(&mut self) -> Option<u32> {
if self.next < self.structref.data.len() {
self.next += 1;
return Some(self.structref.data[self.next-1]);
} else {
return None;
}
}
}
impl<'a> MyTrait<'a> for MyStruct {
type IteratorType = MyIterator<'a>;
fn iter(&'a self) -> Self::IteratorType {
return MyIterator { structref: &self, next: 0 };
}
fn touch(&'a mut self, value: u32) {
}
}
fn touch_all<'a,T>(obj: &'a mut T) where T: MyTrait<'a> {
let data: Vec<u32> = obj.iter().collect();
for value in data {
obj.touch(value);
}
}
Compiling this gives me the error:
error[E0502]: cannot borrow `*obj` as mutable because it is also borrowed as immutable
|
39 | let data: Vec<u32> = obj.iter().collect();
| --- immutable borrow occurs here
40 | for value in data {
41 | obj.touch(value);
| ^^^ mutable borrow occurs here
42 | }
43 | }
| - immutable borrow ends here
By my limited understanding of lifetimes, I would have thought the immutable borrow only extends to the line where I make it - after all the iterator is consumed and I no longer hold any references to obj or data contained in it. Why does the lifetime of the borrow extend to the entire function, and how do I fix this?
Here is a sequence of steps on how I arrived here - running the code should provide the associated compiler errors.
no explicit lifetimes
IteratorType needs lifetime
Unconstrained lifetime parameter
To clarify: I'd like to be able to make calls like this:
fn main() {
let obj: MyStruct = MyStruct { data : vec![] };
touch_all(&mut obj);
}
rather than having to call
touch_all(&mut &obj);
which would be needed for the proposal by mcarton (1st and 2nd comment).

How do I return a reference to something inside a RefCell without breaking encapsulation?

I have a struct that has inner mutability.
use std::cell::RefCell;
struct MutableInterior {
hide_me: i32,
vec: Vec<i32>,
}
struct Foo {
//although not used in this particular snippet,
//the motivating problem uses interior mutability
//via RefCell.
interior: RefCell<MutableInterior>,
}
impl Foo {
pub fn get_items(&self) -> &Vec<i32> {
&self.interior.borrow().vec
}
}
fn main() {
let f = Foo {
interior: RefCell::new(MutableInterior {
vec: Vec::new(),
hide_me: 2,
}),
};
let borrowed_f = &f;
let items = borrowed_f.get_items();
}
Produces the error:
error[E0597]: borrowed value does not live long enough
--> src/main.rs:16:10
|
16 | &self.interior.borrow().vec
| ^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
17 | }
| - temporary value only lives until here
|
note: borrowed value must be valid for the anonymous lifetime #1 defined on the method body at 15:5...
--> src/main.rs:15:5
|
15 | / pub fn get_items(&self) -> &Vec<i32> {
16 | | &self.interior.borrow().vec
17 | | }
| |_____^
The problem is that I can't have a function on Foo that returns a borrowed vec, because the borrowed vec is only valid for the lifetime of the Ref, but the Ref goes out of scope immediately.
I think the Ref must stick around because:
RefCell<T> uses Rust's lifetimes to implement 'dynamic borrowing', a process whereby one can claim temporary, exclusive, mutable access to the inner value. Borrows for RefCell<T>s are tracked 'at runtime', unlike Rust's native reference types which are entirely tracked statically, at compile time. Because RefCell<T> borrows are dynamic it is possible to attempt to borrow a value that is already mutably borrowed; when this happens it results in task panic.
Now I could instead write a function like this that returns the entire interior:
pub fn get_mutable_interior(&self) -> std::cell::Ref<MutableInterior>;
However this potentially exposes fields (MutableInterior.hide_me in this example) that are really private implementation details to Foo.
Ideally I just want to expose the vec itself, potentially with a guard to implement the dynamic borrowing behavior. Then callers do not have to find out about hide_me.
Instead of creating a brand new type, you can use Ref::map (since Rust 1.8). This has the same result as Levans' existing answer:
use std::cell::Ref;
impl Foo {
pub fn get_items(&self) -> Ref<'_, Vec<i32>> {
Ref::map(self.interior.borrow(), |mi| &mi.vec)
}
}
You can also use new features like impl Trait to hide the Ref from the API:
use std::cell::Ref;
use std::ops::Deref;
impl Foo {
pub fn get_items(&self) -> impl Deref<Target = Vec<i32>> + '_ {
Ref::map(self.interior.borrow(), |mi| &mi.vec)
}
}
You can create a new struct similar to the Ref<'a,T> guard returned by RefCell::borrow(), in order to wrap this Ref and avoid having it going out of scope, like this:
use std::cell::Ref;
struct FooGuard<'a> {
guard: Ref<'a, MutableInterior>,
}
then, you can implement the Deref trait for it, so that it can be used as if it was a &Vec<i32>:
use std::ops::Deref;
impl<'b> Deref for FooGuard<'b> {
type Target = Vec<i32>;
fn deref(&self) -> &Vec<i32> {
&self.guard.vec
}
}
after that, update your get_items() method to return a FooGuard instance:
impl Foo {
pub fn get_items(&self) -> FooGuard {
FooGuard {
guard: self.interior.borrow(),
}
}
}
and Deref does the magic:
fn main() {
let f = Foo {
interior: RefCell::new(MutableInterior {
vec: Vec::new(),
hide_me: 2,
}),
};
let borrowed_f = &f;
let items = borrowed_f.get_items();
let v: &Vec<i32> = &items;
}
You can wrap the Vec in an Rc.
use std::cell::RefCell;
use std::rc::Rc;
struct MutableInterior {
hide_me: i32,
vec: Rc<Vec<i32>>,
}
struct Foo {
interior: RefCell<MutableInterior>,
}
impl Foo {
pub fn get_items(&self) -> Rc<Vec<i32>> {
self.interior.borrow().vec.clone() // clones the Rc, not the Vec
}
}
fn main() {
let f = Foo {
interior: RefCell::new(MutableInterior {
vec: Rc::new(Vec::new()),
hide_me: 2,
}),
};
let borrowed_f = &f;
let items = borrowed_f.get_items();
}
When you need to mutate the Vec, use Rc::make_mut to obtain a mutable reference to the Vec. If there are still other Rcs referring to the Vec, make_mut will dissociate the Rc from the other Rcs, clone the Vec and update itself to refer to that new Vec, then give you a mutable reference to it. This ensures that the value in the other Rcs doesn't suddenly change (because Rc by itself doesn't provide interior mutability).

Resources