Cannot assign a new enum value to a field of a struct - rust

I've a Game struct
pub struct Game {
pub status: Status
}
Where Status is an Enum
pub Status {
Initializing,
Running,
End
}
I have this code as implementation of game, should be the main loop, oversimplified now only to evidence the issue
pub fn run(&self) {
&self.status = Status::ExitGame;
}
Compiler is telling I cannot assign to the expression
--> src\game\game.rs:262:22
|
262 | &self.status = Status::End;
| ------------ ^
| |
| cannot assign to this expression
Could you explain me why I cannot do this?

You cannot assign to &self.status, this is a temporary reference. You can assign to self.status, but you'll have to make the method take &mut self.

Note: I accepted as valid the answer from #chayim-friedman. I am only expanding the answer for my self (and hope future googlers)
I modified calling code from
fn main() {
let game = Game::new();
game.run();
}
to
fn main() {
let mut game = Game::new();
game.run();
}
and, as suggested, modified
pub fn run(&self) {
&self.status = Status::ExitGame;
}
to
pub fn run(&mut self) {
self.status = Status::ExitGame;
}

Related

Pass self as mutable reference while iterating over collection [duplicate]

This question already has answers here:
Modifying one attribute of a struct while iterating over another attribute
(4 answers)
Closed last month.
I want to iterate over a vector (or map) of actors in a world struct. The actors need access to the world as they might need to get information about the world, but can also change the state of the world. I should this be done properly in rust?
struct Actor {
}
impl Actor {
pub fn step(&mut self, world: &mut World) {
world.act();
}
}
struct World {
actors: Vec<Actor>,
state: u32
}
impl World {
pub fn step(&mut self) {
for actor in self.actors.iter_mut() {
actor.step(self);
}
}
pub fn act(&mut self) {
self.state += 1;
}
}
fn main() {
}
This code give the error:
error[E0499]: cannot borrow `*self` as mutable more than once at a time
--> src/main.rs:18:24
|
17 | for actor in self.actors.iter_mut() {
| ----------------------
| |
| first mutable borrow occurs here
| first borrow later used here
18 | actor.step(self);
| ^^^^ second mutable borrow occurs here
For more information about this error, try `rustc --explain E0499`.
error: could not compile `actors` due to previous error
You can't. It is impossible to mutate something while iterating over it, and in your current layout, Actor::step() would have the power to modify the actors list. So your situation is impossible, and Rust is correct that it shouldn't be allowed.
The real question is: Does your step function really require the list of actors? If not, I would solve the situation by splitting the list of actors and the state into two objects. That way, you can iterate over actors while only modifying state:
struct Actor {}
impl Actor {
pub fn step(&mut self, state: &mut WorldState) {
state.act();
}
}
struct WorldState {
some_value: u32,
}
struct World {
actors: Vec<Actor>,
state: WorldState,
}
impl World {
pub fn step(&mut self) {
for actor in self.actors.iter_mut() {
actor.step(&mut self.state);
}
}
}
impl WorldState {
pub fn act(&mut self) {
self.some_value += 1;
}
}
A somewhat simple solution is to pass exactly what you need.
impl Actor {
fn step(&mut self, state: &mut u32) {
*state += 1;
}
}
impl World {
pub fn step(&mut self) {
for actor in self.actors.iter_mut() {
actor.step(&mut self.state);
}
}
}

Trouble with digraphs: cannot borrow as mutable

I created a library to deal with digraphs: nodes that link (reference counted) to zero or one other nodes (as in linked lists, but in a digraph a node can be linked to by more than one node).
I am trying to use my library to create a list with a current node:
struct ListWithPointer<'a> {
pub nodes: DigraphNodeRef<String>,
pub current_node: Option<&'a mut DigraphNodeRef<String>>,
}
current_node points to a link in the list.
Now I am trying to move current node to the next element of the list (or to the beginning if the list ended):
fn next_node<'a>(this: &'a mut ListWithPointer<'a>) {
if this.current_node.is_some() {
this.current_node.iter_mut().for_each(|a| {
(*a).as_rc_mut().iter_mut()
.for_each(|rc| this.current_node = Some(&mut Arc::get_mut(rc).unwrap().next));
});
} else {
this.current_node = Some(&mut this.nodes);
}
}
but whatever I do, it fails with an error like:
error[E0500]: closure requires unique access to `this.current_node` but it is already borrowed
--> src/lib.rs:150:51
|
148 | fn next_node<'a>(this: &'a mut ListWithPointer<'a>) {
| -- lifetime `'a` defined here
149 | if this.current_node.is_some() {
150 | this.current_node.iter_mut().for_each(|a| {
| ---------------------------- ^^^ closure construction occurs here
| |
| borrow occurs here
| argument requires that `this.current_node` is borrowed for `'a`
151 | (*a).as_rc_mut().iter_mut()
152 | .for_each(|rc| this.current_node = Some(&mut Arc::get_mut(rc).unwrap().next));
| ----------------- second borrow occurs due to use of `this.current_node` in closure
Help to rewrite without errors.
Here is the library code:
use std::sync::Arc;
#[derive(Clone)]
pub struct DigraphNode<T> {
pub next: DigraphNodeRef<T>, // I made it `pub` to be able `item.next.next()` to remove an item from the middle.
data: T,
}
impl<T> DigraphNode<T> {
fn new(next: DigraphNodeRef<T>, data: T) -> Self {
Self { next, data }
}
}
pub struct DigraphNodeRef<T> {
rc: Option<Arc<DigraphNode<T>>>,
}
impl<T> DigraphNodeRef<T> {
pub fn new() -> Self {
Self {
rc: None
}
}
pub fn from_node(value: DigraphNode<T>) -> Self {
Self::from(Some(Arc::new(value)))
}
pub fn from(rc: Option<Arc<DigraphNode<T>>>) -> Self {
Self {
rc
}
}
pub fn as_rc(&self) -> &Option<Arc<DigraphNode<T>>> {
&self.rc
}
pub fn as_rc_mut(&mut self) -> &mut Option<Arc<DigraphNode<T>>> {
&mut self.rc
}
pub fn is_none(&self) -> bool {
self.rc.is_none()
}
pub fn remove(&mut self) -> bool {
if let Some(rc) = self.rc.clone() {
self.rc = rc.next.rc.clone();
true
} else {
false
}
}
pub fn prepend(&mut self, value: T) -> Self {
let new_node = DigraphNode::new(self.clone(), value);
let new_node_ref = DigraphNodeRef::from_node(new_node);
*self = new_node_ref.clone();
new_node_ref
}
pub fn node(&self) -> Option<DigraphNode<T>>
where T: Clone
{
self.rc.clone().map(|node| (*node).clone())
}
/// TODO: Should return a reference.
pub fn data(&self) -> Option<T>
where T: Clone
{
self.rc.clone().map(|node| (*node).data.clone())
}
pub fn values(self) -> DigraphNodeValuesIterator<T> {
DigraphNodeValuesIterator {
underlying: self.clone()
}
}
}
impl<T> Clone for DigraphNodeRef<T> {
fn clone(&self) -> Self {
Self { rc: self.rc.clone() }
}
}
impl<T> Iterator for DigraphNodeRef<T> {
type Item = Arc<DigraphNode<T>>;
fn next(&mut self) -> Option<Self::Item> {
if let Some(rc) = self.rc.clone() {
self.rc = rc.next.rc.clone();
Some(rc.clone())
} else {
None
}
}
}
pub struct DigraphNodeValuesIterator<T> {
underlying: DigraphNodeRef<T>,
}
impl<T: Clone> Iterator for DigraphNodeValuesIterator<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
self.underlying.next().map(|node| node.data.clone())
}
}
In Rust the mutable access is ensured to be exclusive, i.e. if you hold a reference, some other code can't grab a mutable reference.
Problem is this line:
this.current_node.iter_mut().for_each(...)
It grabs a mutable access to current_node, so it can't regain it again down the line.
Not to mention that iterating over Option is a strange decision.
If you want to move current_node to a different place, I'd try to reorganize your code such that reads are separate from writes, and they are performed in a sequence, instead of trying to do it in one go:
// detach the current_node for moving
if let Some(current_node_to_move) = this.current_node.take() {
let new_current_node_ref: &mut ... = ... // find new location logic
new_current_node_ref.replace(current_node_to_move);
} else {
...
}
Here in line 1 it does a write None update to current_node via this, but immediately relinquishes the mutable reference. Line 2 does a read (search), but also grabs a mutable reference to a new location. Line 3 writes to this location.
To get the linked list implementation right, I recommend https://rust-unofficial.github.io/too-many-lists/

How to resolve basic borrow issues?

I'm pretty new to rust and I'm stuck on whats probably a very simple question about borrowing. I've simplified my code to as below:
pub struct MyStruct {
pub val: i32
}
impl MyStruct {
pub fn new(val: i32) -> Self {
MyStruct {
val
}
}
}
pub struct MyStructVec {
pub vec: Vec::<MyStruct>
}
impl MyStructVec {
pub fn new() -> Self {
MyStructVec {
vec: Vec::new()
}
}
pub fn insert(&mut self, mut my_struct: MyStruct) {
self.vec.push(my_struct);
}
fn run(&mut self) {
for s in self.vec.iter_mut() {
s.val = s.val + 1;
self.edit(s);
}
}
fn edit(&self, my_struct: &mut MyStruct) {
my_struct.val = my_struct.val * 2;
}
}
fn main() {
let mut my_struct1 = MyStruct::new(69);
let mut my_struct2 = MyStruct::new(420);
let mut my_struct_vec = MyStructVec::new();
my_struct_vec.insert(my_struct1);
my_struct_vec.insert(my_struct2);
my_struct_vec.run();
}
When I run this i get the following error:
error[E0502]: cannot borrow `*self` as immutable because it is also borrowed as mutable
--> src/main.rs:33:13
|
31 | for s in self.vec.iter_mut() {
| -------------------
| |
| mutable borrow occurs here
| mutable borrow later used here
32 | s.val = s.val + 1;
33 | self.edit(s);
| ^^^^ immutable borrow occurs here
But if I edit my code like this:
fn run(&mut self) {
for s in self.vec.iter_mut() {
s.val = s.val + 1;
//self.edit(s);
s.val = s.val * 2;
}
}
Then it runs perfectly fine. This examples a simplified case but in my actual code I might just want to separate out my code into a separate function for easier readability like with the edit function. So what is the proper way to do this in Rust? Thanks very much!
I think the error is that for some reason you are making your MyStructVec modify MyStruct when it could be simple a method on MyStruct. You are messing around with more references that you need, and you are not really taking the ones you need. It seems fair that edit should be encapsulated in the object that is gonna modify:
impl MyStruct {
...
fn edit(&mut self) {
self.val = self.val * 2;
}
}
...
impl MyStructVec {
...
fn run(&mut self) {
for s in self.vec.iter_mut() {
s.val = s.val + 1;
s.edit();
}
}
}
Playground

How do I implement an iterator from a vector of std::Rc<std::RefCell<T>> smart pointers?

I'm trying to understand how to work with interior mutability. This question is strongly related to my previous question.
I have a generic struct Port<T> that owns a Vec<T>. We can "chain" port B to port A so, when reading the content of port A, we are able to read the content of port B. However, this chaining is hidden to port A's reader. That is why I implemented the iter(&self) method:
use std::rc::Rc;
pub struct Port<T> {
values: Vec<T>,
ports: Vec<Rc<Port<T>>>,
}
impl <T> Port<T> {
pub fn new() -> Self {
Self { values: vec![], ports: vec![] }
}
pub fn add_value(&mut self, value: T) {
self.values.push(value);
}
pub fn is_empty(&self) -> bool {
self.values.is_empty() && self.ports.is_empty()
}
pub fn chain_port(&mut self, port: Rc<Port<T>>) {
if !port.is_empty() {
self.ports.push(port)
}
}
pub fn iter(&self) -> impl Iterator<Item = &T> {
self.values.iter().chain(
self.ports.iter()
.flat_map(|p| Box::new(p.iter()) as Box<dyn Iterator<Item = &T>>)
)
}
pub fn clear(&mut self) {
self.values.clear();
self.ports.clear();
}
}
The application has the following pseudo-code behavior:
create ports
loop:
fill ports with values
chain ports
iterate over ports' values
clear ports
The main function should look like this:
fn main() {
let mut port_a = Rc::new(Port::new());
let mut port_b = Rc::new(Port::new());
loop {
port_a.add_value(1);
port_b.add_value(2);
port_a.chain_port(port_b.clone());
for val in port_a.iter() {
// read data
};
port_a.clear();
port_b.clear();
}
}
However, the compiler complains:
error[E0596]: cannot borrow data in an `Rc` as mutable
--> src/modeling/port.rs:46:9
|
46 | port_a.add_value(1);
| ^^^^^^ cannot borrow as mutable
|
= help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Rc<Port<i32>>`
I've been reading several posts etc., and it seems that I need to work with Rc<RefCell<Port<T>>> to be able to mutate the ports. I changed the implementation of Port<T>:
use std::cell::RefCell;
use std::rc::Rc;
pub struct Port<T> {
values: Vec<T>,
ports: Vec<Rc<RefCell<Port<T>>>>,
}
impl<T> Port<T> {
// snip
pub fn chain_port(&mut self, port: Rc<RefCell<Port<T>>>) {
if !port.borrow().is_empty() {
self.ports.push(port)
}
}
pub fn iter(&self) -> impl Iterator<Item = &T> {
self.values.iter().chain(
self.ports
.iter()
.flat_map(|p| Box::new(p.borrow().iter()) as Box<dyn Iterator<Item = &T>>),
)
}
// snip
}
This does not compile either:
error[E0515]: cannot return value referencing temporary value
--> src/modeling/port.rs:35:31
|
35 | .flat_map(|p| Box::new(p.borrow().iter()) as Box<dyn Iterator<Item = &T>>),
| ^^^^^^^^^----------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| | |
| | temporary value created here
| returns a value referencing data owned by the current function
I think I know what the problem is: p.borrow() returns a reference to the port being chained. We use that reference to create the iterator, but as soon as the function is done, the reference goes out of scope and the iterator is no longer valid.
I have no clue on how to deal with this. I managed to implement the following unsafe method:
pub fn iter(&self) -> impl Iterator<Item = &T> {
self.values.iter().chain(self.ports.iter().flat_map(|p| {
Box::new(unsafe { (&*p.as_ref().as_ptr()).iter() }) as Box<dyn Iterator<Item = &T>>
}))
}
While this works, it uses unsafe code, and there must be a safe workaround.
I set a playground for more details of my application. The application compiles and outputs the expected result (but uses unsafe code).
You can't modify anything behind an Rc, that's correct. While this might be solved with a RefCell, you don't want to go down that road. You might come into a situation where you'd need to enforce a specific clean() order or similar horrors.
More important: your main is fundamentally flawed, ownership-wise. Take these lines:
let mut port_a = Port::new();
let mut port_b = Port::new();
loop {
// Creates an iummutable borrow of port_b with same lifetime as port_a!
port_a.chain_port(port_b);
// ...
// A mutable borrow of port_b.
// But the immutable borrow from above persists across iterations.
port_b.clear();
// Or, even if you do fancy shenanigans at least until this line.
port_a.clear();
}
To overcome this, just constrain the ports lifetime to one iteration. You currently manually clean them up anyway, so that's already what you're doing conceptually.
Also, I got rid of that recursive iteration, just to simplify things a little more.
#[derive(Clone)]
pub struct Port<'a, T> {
values: Vec<T>,
ports: Vec<&'a Port<'a, T>>,
}
impl<'a, T> Port<'a, T> {
pub fn new() -> Self {
Self {
values: vec![],
ports: vec![],
}
}
pub fn add_value(&mut self, value: T) {
self.values.push(value);
}
pub fn is_empty(&self) -> bool {
self.values.is_empty() && self.ports.is_empty()
}
pub fn chain_port(&mut self, port: &'a Port<T>) {
if !port.is_empty() {
self.ports.push(&port)
}
}
pub fn iter(&self) -> impl Iterator<Item = &T> {
let mut port_stack: Vec<&Port<T>> = vec![self];
// Sensible estimate I guess.
let mut values: Vec<&T> = Vec::with_capacity(self.values.len() * (self.ports.len() + 1));
while let Some(port) = port_stack.pop() {
values.append(&mut port.values.iter().collect());
port_stack.extend(port.ports.iter());
}
values.into_iter()
}
}
fn main() {
loop {
let mut port_a = Port::new();
let mut port_b = Port::new();
port_a.add_value(1);
port_b.add_value(2);
port_a.chain_port(&port_b);
print!("values in port_a: [ ");
for val in port_a.iter() {
print!("{} ", val);
}
println!("]");
}
}

Using a struct to store a reference to a non-Copy value

I need an object that contains a reference to a process child and enables me to execute functions on it.
pub struct Shell {
child: std::process::Child,
}
impl Shell {
pub fn init() -> Shell {
let mut cmd = std::process::Command::new("Command");
let process = cmd.spawn();
let new = Shell {
child: process.unwrap(),
};
new
}
pub fn f1(mut self) {
//do something with self
}
pub fn f2(mut self) {
{
let stdin = self.child.stdin.as_mut().unwrap();
}
let output = self.child.wait_with_output();
}
}
fn main() {
let mut shell = Shell::init();
shell.f1();
shell.f2();
}
error[E0382]: use of moved value: `shell`
--> src/main.rs:28:5
|
27 | shell.f1();
| ----- value moved here
28 | shell.f2();
| ^^^^^ value used here after move
|
= note: move occurs because `shell` has type `Shell`, which does not implement the `Copy` trait
>Try it
The problem is that when I initialize my object, I can call functions on the object only once, because the value is moved on the first call due to standard Rust behaviour.
A simple #[derive(Copy, Clone)] does not work here, because std::process::Child does not seem to implement the Copy trait. Is there a way to circumvent that or wrap it into something copy-able?
Test Implementations
When using a mutable reference as the function argument, the initial problem appears to be solved, however, it is then not possible to access the self.child more than once.
pub struct Shell {
child: std::process::Child,
}
impl Shell {
pub fn init() -> Shell {
let mut cmd = std::process::Command::new("Command");
let process = cmd.spawn();
let new = Shell {
child: process.unwrap(),
};
new
}
pub fn f1(&mut self) {
//do something with self
}
pub fn f2(&mut self) {
{
let stdin = self.child.stdin.as_mut().unwrap();
}
let output = self.child.wait_with_output();
}
}
fn main() {
let mut shell = Shell::init();
shell.f1();
shell.f2();
}
error[E0507]: cannot move out of borrowed content
--> src/main.rs:21:22
|
21 | let output = self.child.wait_with_output();
| ^^^^ cannot move out of borrowed content
>Try it
Is there a way to solve that?
The problem is that self.child has to be consumed by wait_with_output(). This is why self must not be passed to f2 by reference, but by value:
pub struct Shell {
child: std::process::Child,
}
impl Shell {
pub fn init() -> Shell {
let mut cmd = std::process::Command::new("Command");
let process = cmd.spawn();
let new = Shell {
child: process.unwrap(),
};
new
}
pub fn f1(&mut self) {
//do something with self
}
pub fn f2(mut self) {
{
let stdin = self.child.stdin.as_mut().unwrap();
}
let output = self.child.wait_with_output();
}
}
fn main() {
let mut shell = Shell::init();
shell.f1();
shell.f2();
}
>Try it
However this implies that f2 must be the last function that accesses self.child.

Resources