How to call method on struct that has mutable self in Rust - rust

I am having trouble with the following set up:
#[derive(Debug)]
struct SomeStruct {
numbers: Vec<u32>,
}
impl SomeStruct {
fn some_func(&mut self) { // `mut` causes the issue
self.numbers.push(9); // Contrived but need to call self in here.
println!("Hello from some func");
}
}
pub fn main() {
let struct1 = SomeStruct {
numbers: vec![1, 2, 3],
};
let struct2 = SomeStruct {
numbers: vec![99, 98, 97],
};
let mut vec = Vec::new();
vec.push(&struct1);
vec.push(&struct2);
let first = vec.first_mut().unwrap();
// cannot borrow `**first` as mutable, as it is behind a `&` reference
// cannot borrow as mutable rustc(E0596)
first.some_func();
}
There are many questions about mutable & borrowing but I still can't figure it out. Could someone please explain why this is wrong and how to fix it?

The problem is that vec only has shared references, i.e. &SomeStruct instead of SomeStruct or &mut SomeStruct.
The call to some_func() can't succeed in this setup because it requires &mut self. However, there are ways to work around this:
let vec own SomeStruct, e.g.: vec![struct1, struct2]
Push &mut struct1 and &mut struct2 in the vec
use interior mutability, e.g. through RefCell which would allow you to modify data while holding a shared reference
The interior mutability solution would look something like this:
use std::cell::RefCell;
#[derive(Debug)]
struct SomeStruct {
numbers: RefCell<Vec<u32>>,
}
impl SomeStruct {
fn some_func(&self) {
self.numbers.borrow_mut().push(9); // Contrived but need to call self in here.
println!("Hello from some func");
}
}
pub fn main() {
let struct1 = SomeStruct {
numbers: RefCell::new(vec![1, 2, 3]),
};
let struct2 = SomeStruct {
numbers: RefCell::new(vec![99, 98, 97]),
};
let mut vec = Vec::new();
vec.push(&struct1);
vec.push(&struct2);
let first = vec.first().unwrap();
// cannot borrow `**first` as mutable, as it is behind a `&` reference
// cannot borrow as mutable rustc(E0596)
first.some_func();
}

Related

Ensure a variables live long enough to store reference to it

rust beginner here.
I'm trying to learn about lifetimes, but can't manage to wrap my head around something :
I want to build a Vec of struct, and populate it by passing it to the struct so it decides if it want to put itself into or not.
Here is an exemple :
struct MyStruct {
value: bool,
}
impl MyStruct {
fn add_to_vec(&Self, vec: &Vec<&MyStruct>) {
if self.value {
vec.push(&self);
}
}
}
fn main() {
let mut my_vec: Vec<&MyStruct> = Vec::new();
//let's say my_structs is a defined array of MyStruct
for struct in my_structs.iter() {
struct.add_to_vec(&my_vec);
}
}
This code does not compile, because we are not assured that the structs that are referenced in the vec will live longer than the vec itself, thus creating dangling pointers.
How could I use lifetimes (or anything else) to make this work ?
You just need to match the lifetimes, meaning that the vector should store references that live at least as 'self:
#[derive(Debug)]
struct MyStruct {
value: bool,
}
impl MyStruct {
fn add_to_vec<'s>(&'s self, vec: &mut Vec<&'s MyStruct>) {
if self.value {
vec.push(self);
}
}
}
fn main() {
let mut my_vec: Vec<&MyStruct> = Vec::new();
let my_struct = MyStruct {value: true};
let my_struct2 = MyStruct {value: true};
let my_structs = [&my_struct, &my_struct2];
for s in my_structs.iter() {
s.add_to_vec(&mut my_vec);
}
println!("{my_vec:?}");
}
Playground

Allocating struct objects on heap inside loop in rust

I need to allocate structs with a drop trait inside a for loop and have a mutable reference for downstream processing. I have created this minimal example code that I can't compile with rust version 1.59. I have tried using the internal mutability with Rc and RefCell as well.
use std::cell::RefCell;
use std::rc::Rc;
// MyVec with Drop Trait
struct MyVec {
vec: Vec<i32>,
}
impl Drop for MyVec {
fn drop(&mut self) {
println!("Dropping MyVec with data `{:?}`!", self.vec);
}
}
impl MyVec {
// Get a mutable slice
fn mut_slice(&mut self) -> &mut [i32]{
return &mut self.vec[..]
}
}
pub fn test() {
// Needed for downstream purposes
let mut all_slices = Vec::new();
// Storing reference counter Rc and RefCell combo
// Hoping to prevent allocated MyVec objects from dropping and have one mutable reference
let mut all_refs = Vec::new();
for _i in 0..1 {
let my_vec = Rc::new(RefCell::new(MyVec {
vec: vec![1, 2, 3]
}));
// Make a clone of my_vec to prevent it from dropping
all_refs.push(Rc::clone(&my_vec));
let mut my_vec_mut = my_vec.borrow_mut();
let x = my_vec_mut.mut_slice();
all_slices.push(x);
}
println!("{:?}", all_slices);
}
The same code works when I unroll the loop and write the following code:
pub fn test() {
// Needed for downstream purposes
let mut all_slices = Vec::new();
// Storing reference counter Rc and RefCell combo
// Hoping to prevent allocated MyVec objects from dropping and have one mutable reference
let mut all_refs = Vec::new();
let my_vec = Rc::new(RefCell::new(MyVec {
vec: vec![1, 2, 3]
}));
// Make a clone of my_vec to prevent it from dropping
all_refs.push(Rc::clone(&my_vec));
let mut my_vec_mut = my_vec.borrow_mut();
let x = my_vec_mut.mut_slice();
all_slices.push(x);
println!("{:?}", all_slices);
}
Update: Thanks to Masklinn's comments, I fixed the code. I needed to create objects in the loop and required a mutable reference to its internal data field outside the scope of the loop. The rust compiler showed an error that the references outlive the object itself. Finally, I used a separate loop to allocate the objects and a second loop with iter_mut to create mutable references. Here is the final code:
pub fn test() {
// Needed for downstream purposes
let mut all_slices = Vec::new();
// Hoping to prevent allocated MyVec objects from dropping and have one mutable reference
let mut all_vecs = Vec::new();
for _i in 0..1 {
all_vecs.push(MyVec {
vec: vec![1, 2, 3]
});
}
for my_vec in all_vecs.iter_mut() {
all_slices.push(my_vec.mut_slice());
}
println!("{:?}", all_slices);
}

How to borrow two disjoint fields when the borrow is behind a method call?

In the code below I have a struct Foo with a read-only field a and a bunch of read-write fields. When borrowing the separate fields directly from the struct there's no issue borrowing. However, when I hide the borrow behind a method call, it says I no longer can borrow.
#![allow(unused_variables)]
#![allow(unused_mut)]
#![allow(dead_code)]
struct Foo {
a: Vec<i32>, // Public read-only field.
pub b: Vec<f32>, // Public read-write field.
pub c: Vec<i32>, // Public read-write field.
// ... maybe more fields ...
pub z: Vec<bool>, // Public read-write field.
}
impl Foo {
pub fn new() -> Self {
Self {
a: vec![1, 2, 3],
b: vec![1.0, 2.0, 3.0],
c: vec![-3, 0, 3],
z: vec![false, true],
}
}
pub fn borrow_a(&self) -> &Vec<i32> {
&self.a
}
}
pub fn main() {
let mut foo = Foo::new();
{ // This is okay.
let x = &foo.a; // Immutably borrow `a`.
let mut y = &mut foo.b; // Mutably borrow `b`.
for i in x { } // Immutably use `a`.
}
{ // This creates an error.
let x = foo.borrow_a(); // Immutably borrow `a`.
let mut y = &mut foo.b; // Mutably borrow `b`.
for i in x { } // Immutably use `a`.
}
}
Rust playground
error[E0502]: cannot borrow `foo.b` as mutable because it is also borrowed as immutable
--> src/main.rs:39:21
|
38 | let x = foo.borrow_a(); // Immutably borrow `a`.
| --- immutable borrow occurs here
39 | let mut y = &mut foo.b; // Mutably borrow `b`.
| ^^^^^^^^^^ mutable borrow occurs here
40 | for i in x { } // Immutably use `a`.
| - immutable borrow later used here
Is there some way I can tell the compiler that the code is fine and I'm borrowing two disjoint fields? Or is there some other ergonomic solution?
Different techniques that could be used
Use Splitting Borrow
This comment suggest using Splitting Borrow to borrow the fields. This will work as shown in the example below.
However, this is not an ergonomic API for the user of for the maintainer. If they've borrowed fields in foo and now also want to borrow a, they'd have to rewrite their borrows to go through the Split Borrow method. They also have to match against the fields they want to borrow. Since they match against a tuple, it's not entirely clear which fields they're matching against.
Also, introducing a new public field in Foo would break everything, as the signature of split_borrow would have to change.
All in all, this can work when the amount of fields is low.
#![allow(unused_variables)]
#![allow(unused_mut)]
#![allow(dead_code)]
struct Foo {
a: Vec<i32>, // Public read-only field.
pub b: Vec<f32>, // Public read-write field.
pub c: Vec<i32>, // Public read-write field.
// ... maybe more fields ...
pub z: Vec<bool>, // Public read-write field.
}
impl Foo {
pub fn new() -> Self {
Self {
a: vec![1, 2, 3],
b: vec![1.0, 2.0, 3.0],
c: vec![-3, 0, 3],
z: vec![false, true],
}
}
pub fn split_borrow(&mut self) -> (&Vec<i32>, &mut Vec<f32>, &mut Vec<i32>, &mut Vec<bool>) {
(&self.a, &mut self.b, &mut self.c, &mut self.z)
}
}
pub fn main() {
let mut foo = Foo::new();
{ // This is okay.
let (a, ref mut b, ..) = foo.split_borrow();
for i in a { }
}
{ // This is okay.
let (a, _, _, ref mut z) = foo.split_borrow();
for i in a { }
}
{ // This is okay if we re-borrow the values
// between each use.
let (a, ref mut b, ..) = foo.split_borrow();
b.push(4.0);
let (a, _, _, ref mut z) = foo.split_borrow();
// Can't use b from this point.
z.push(false);
println!("{:?}, {:?}", a, z);
}
{ // It's not okay to mix-and-match variables
// from different borrows, as they're exclusively
// bound to `foo`.
let (a, ref mut b, ..) = foo.split_borrow();
let (_, _, _, ref mut z) = foo.split_borrow();
for i in a { }
}
}
Rust Playground
Use Interior mutability
This answer shows how to emulate the old construct of using mut in fields by wrapping the type in a std::cell::Cell. This could be a solution if we were to wrap all the mutable fields in a Cell and only operate on immutable borrows of Foo.
However, this restrict the data to be single threaded, as std::cell::Cell implements !Sync. It also restrict the data to only be Copy. Furthermore, this does allow the mutable fields to mutate in places of the code where we've passed an immutable reference and therefore expect them to not be mutated. I don't see this as a solution, but can work.
Wrap in a ReadOnly type
This answer shows how to wrap the read-only value into an immutable struct. This is so far the cleanest and most ergonomic solution, as shown in the example below. As all fields are now public, the borrow checker is able to figure out that we're actually borrowing disjoint fields.
The only inconvenience is that you need to define the ReadOnly structure in each module. This is because you want get_mut to only be accessible by the structure that owns ReadOnly (in other words, get_mut can't be public).
#![allow(unused_variables)]
#![allow(unused_mut)]
#![allow(dead_code)]
use std::ops::Deref;
struct ReadOnly<T> {
data: T,
}
impl<T> ReadOnly<T> {
pub fn new(data: T) -> Self {
ReadOnly { data }
}
pub fn get(&self) -> &T {
&self.data
}
// Private function for mutating the
// data from within Foo itself.
fn get_mut(&mut self) -> &mut T {
&mut self.data
}
}
impl<T> Deref for ReadOnly<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.data
}
}
struct Foo {
pub a: ReadOnly<Vec<i32>>, // Public read-only field.
pub b: Vec<f32>, // Public read-write field.
pub c: Vec<i32>, // Public read-write field.
// ... maybe more fields ...
pub z: Vec<bool>, // Public read-write field.
}
impl Foo {
pub fn new() -> Self {
Self {
a: ReadOnly::new(vec![1, 2, 3]),
b: vec![1.0, 2.0, 3.0],
c: vec![-3, 0, 3],
z: vec![false, true],
}
}
}
pub fn main() {
let mut foo = Foo::new();
{ // This now works.
let x = foo.a.get(); // Immutably borrow `a`.
let mut y = &mut foo.b; // Mutably borrow `b`.
for i in x { } // Immutably use `a`.
}
{ // This is now erroneous.
let mut x = &mut foo.a; // Can still borrow ReadOnly as mutable.
let mut y = &mut foo.b; // Mutably borrow `b`.
for i in x.iter_mut() { } // Can't use `a` as mutable.
}
}
Rust Playground
TL;DR
Read-only accessors, or "getters", for individual fields will easily break valid borrowing. Instead, the fields should instead be wrapped in a ReadOnly structure, or a Split Borrow method should be provided if the amount of fields is low.

How can I tell the compiler to release a borrow in a struct without dropping the entire struct?

I have the following struct which represents a plan for a numeric computation:
pub struct NfftPlan<'a> {
x: Option<&'a [f64]>,
f_hat: Option<&'a [Complex64]>,
// ...
}
It has a set_f_hat method:
pub fn set_f_hat(&mut self, f_hat: &'a [Complex64]) {
self.f_hat = Some(f_hat);
}
and an execute method:
pub fn execute(&self) -> Vec<Complex64>
which uses f_hat immutably.
I want to use this in the following way:
let mut f_hat = vec![1,2,3,4];
let plan = NfftPlan::new()
plan.set_f_hat(&f_hat);
plan.execute();
f_hat[0] = 3; // Change f_hat to a new value
plan.execute(); //New computation
This fails because I cant mutate f_hat while plan still exists.
Is there a way for plan to release the borrow to f_hat which would allow me to mutate the f_hat vector?
Something like this:
releasedata(&self) {
self.f_hat = None
} //Now the compiler forgets that plan would hold an borrow to f_hat
I know that Rust does not allow me to change the vector while a borrow to it exists, in this case via the f_hat reference in the NfftPlan struct.
I would like a way to tell the compiler to drop the reference to the vector in the NfftPlan struct without dropping the entire struct.
Explanation
How can I tell the compiler to release a borrow
You cannot, period. This isn't something you "tell" the compiler, the compiler knows all. You can only completely stop using the reference.
without dropping the entire struct
Dropping doesn't clear the borrow, only the borrow no longer being used does, which may happen from the drop.
f_hat[0] = 3; // Change f_hat to a new value
plan.execute(); //New computation
This is exactly one of the types of code that Rust tries to prevent. It is not obvious at all that plan.execute() should return a different value because some apparently unrelated value has changed.
Solutions
Encode it in the type system
I'd structure my types to reflect how they need to be used, creating throwaway values that can execute only once everything has been combined together. This means that the structure that borrows f_mut is dropped as soon as it's done; note how this removes the Option completely:
fn main() {
let mut f_hat = 42;
let plan = Plan::default();
plan.set_f_hat(&f_hat).execute();
f_hat = 3;
plan.set_f_hat(&f_hat).execute();
}
#[derive(Debug, Default)]
struct Plan<'a> {
x: Option<&'a i32>,
}
impl<'a> Plan<'a> {
fn set_f_hat(&self, f_hat: &'a i32) -> PlanPlus<'a> {
PlanPlus { x: self.x, f_hat }
}
}
#[derive(Debug)]
struct PlanPlus<'a> {
x: Option<&'a i32>,
f_hat: &'a i32,
}
impl<'a> PlanPlus<'a> {
fn execute(&self) {}
}
Use interior mutability and reference counting
use std::{cell::Cell, rc::Rc};
#[derive(Debug, Default)]
struct Plan<'a> {
x: Option<&'a i32>,
f_hat: Option<Rc<Cell<i32>>>,
}
impl<'a> Plan<'a> {
fn set_f_hat(&mut self, f_hat: Rc<Cell<i32>>) {
self.f_hat = Some(f_hat);
}
fn execute(&self) {}
}
fn main() {
let f_hat = Rc::new(Cell::new(42));
let mut plan = Plan::default();
plan.set_f_hat(f_hat.clone());
plan.execute();
f_hat.set(3);
plan.execute();
}
Recognize that the member is mutable
#[derive(Debug, Default)]
struct Plan<'a> {
x: Option<&'a i32>,
f_hat: Option<&'a mut i32>,
}
impl<'a> Plan<'a> {
fn f_hat(&mut self) -> &mut Option<&'a mut i32> {
&mut self.f_hat
}
fn execute(&self) {}
}
fn main() {
let mut f_hat = 42;
let mut plan = Plan::default();
*plan.f_hat() = Some(&mut f_hat);
plan.execute();
**plan.f_hat().as_mut().unwrap() = 3;
plan.execute();
}
See also:
What are the options to end a mutable borrow in Rust?
Drop a immutable borrow to make a mutable borrow
Moved variable still borrowing after calling `drop`?

Accessing two vectors in a struct locked by a mutex [duplicate]

This question already has an answer here:
Error while trying to borrow 2 fields from a struct wrapped in RefCell
(1 answer)
Closed 3 years ago.
I have a struct with two vectors that is passed through a function while in a Arc<Mutex<TwoArrays>>.
pub struct TwoArrays {
pub a: Vec<i32>,
pub b: Vec<i32>,
}
fn add_arrays(mut foo: Arc<Mutex<TwoArrays>>) {
let mut f = foo.lock().unwrap();
//Loop A: compiles
for i in 0..f.a.len() {
for j in 0..f.b.len() {
f.b[j] += f.a[i];
}
}
//Loop B: does not compile
for i in f.a.iter() {
for j in 0..f.b.len() {
f.b[j] += i;
}
}
}
When I make a loop that uses an iterator, with another loop writing inside(Loop B), the compiler complains:
error[E0502]: cannot borrow `f` as mutable because it is also borrowed as immutable
Loop A Compiles.
Why is there a immutable borrow on f?
Can I make it only borrow each array individually? That is, a mutable borrow of f.b and a immutable borrow of f.a?
Why does this not happen when I pass TwoArrays directly? It only happens when I pass it in as an Arc<Mutex<TwoArrays>>
When you unwrap the LockResult you get a MutexGuard, and not directly a TwoArrays. You can use it as if it was a TwoArrays because it implements Deref and DerefMut.
When you try to write 2 loops, you try to use both deref and deref_mut at once: that's impossible:
pub struct TwoArrays {
pub a: Vec<i32>,
pub b: Vec<i32>,
}
fn add_arrays(mut foo: Arc<Mutex<TwoArrays>>) {
let mut f = foo.lock().unwrap();
//Loop B: does not compile
for i in f.a.iter() {
// ^~~~~~~~~~~~~~~~~~~ Implicit call to `deref` here.
for j in 0..f.b.len() {
// ^~~~~~~~~~~~ Another implicit call to `deref` here.
f.b[j] += i;
// ^~~~~~~~~~~~~~~~~~~~ Implicit call to `deref_mut` here.
}
}
}
If you deref_mut once before doing the loops, everything works fine:
use std::{sync::{Arc, Mutex}, ops::DerefMut};
pub struct TwoArrays {
pub a: Vec<i32>,
pub b: Vec<i32>,
}
fn add_arrays(foo: &mut Arc<Mutex<TwoArrays>>) {
let mut mutex_guard = foo.lock().unwrap();
let real_two_arrays = mutex_guard.deref_mut();
for i in &mut real_two_arrays.a {
for j in &real_two_arrays.b {
*i += *j;
}
}
}
You can access to two vector in a struct like following:
use std::mem;
#[derive(Debug)]
pub struct TwoArrays {
pub a: Vec<i32>,
pub b: Vec<i32>,
}
fn add_arrays(mut foo: TwoArrays) {
let a = foo.a.clone();
let mut b = foo.b.clone();
for i in a.iter() {
let mut index = 0;
for _j in b.iter_mut() {
let mut new_value = i.clone() + foo.b[index as usize].clone();
mem::swap(&mut foo.b[index as usize], &mut new_value);
index = index + 1;
}
}
println!("Arrays A: {:?}", &foo.a);
println!("Arrays A: {:?}", &foo.b);
}
fn main() {
let a = vec![1i32, 2i32, 3i32];
let b = vec![4i32, 5i32, 6i32];
let two_arrays = TwoArrays { a, b };
// let foo = Arc::new(Mutex::new(two_arrays));
add_arrays(two_arrays);
}
Playground
Why is there an immutable borrow for f?
Because you tried to iterate it with iter() not the iter_mut()
And why does this not happen when I pass TwoArrays directly? It only happens when I pass it in as an Arc<Mutex<TwoArrays>>
You can pass it as naked struct without the need of Arc<Mutex<>> with the sample code.
If you insist on using Arc<Mutex<>> to pass the same object around with an atomic reference you can change the function signature to the following:
fn add_arrays(mut foo: Arc<Mutex<TwoArrays>>)
And you need to lock() and get that reference from the Arc with following:
let foo = foo.lock().unwrap();
Playground With Arc Usage

Resources