I have 3 structs Player, Dealer and Cards. Dealer contains a vec of Cards whiles Player contains a vec of references to some of those cards that the dealer has.
pub struct Dealer{
cards: Vec<Card>,
}
pub struct Player<'a>{
pub cards: Vec<&'a Card>,
}
I have some methods that I implemented for Dealer and Player to create a dealer and a vec of players respectively.
impl Dealer{
pub fn new() -> Self{
//Some code here
}
}
impl Player<'_>{
pub fn create(number: i32) -> Vec<Self>{
//Some code here
}
}
Now I wish to write a function that would iteratively add items to each player's vec.
The function below retrieves a reference to a Card item in the dealer's vec.
pub fn draw_next(&self) -> &Card{
self.cards.get(//index would be here).unwrap()
}
For now you may disregard the value I use as index.
This is how I add the items to each player's vec.
let d: Dealer = Dealer::new();
let players: Vec<Player> = Player::create(4);
for each_player in players.iter_mut(){
each_player.cards.push(d.draw_next());
}
This executes without any issue however when I change the draw_next to this:
But for some reason, I need a mutable reference at draw_next
pub fn draw_next(&mut self) -> &Card{
self.cards.get(//index would be here).unwrap()
}
but when I run this:
let mut d: Dealer = Dealer::new();
let players: Vec<Player> = Player::create(4);
for each_player in players.iter_mut(){
each_player.cards.push(d.draw_next());
}
I get this error:
error[E0499]: cannot borrow `d` as mutable more than once at a time
`d` was mutably borrowed here in the previous iteration of the loop
Why is the above code giving me the above error?
I do not expect this error because the following code doesn't give me any errors
struct SS{
i: i32,
}
impl SS{
fn do_this(&mut self){
}
}
fn main(){
let mut name: SS = SS{i: 4};
for _ in 0..3{
name.do_this();
}
}
although they both make use of mutable references in a loop.
For my complete code:https://github.com/nisaacdz/Poker_game/tree/master/src
Related
Here's an example of a problem I ran into:
pub struct Item {
name: String,
value: LockableValue, // another struct that I'd like to mutate
}
impl Item {
pub fn name(&self) -> &str {
&self.name
}
pub fn value_mut(&mut self) -> &mut LockableValue {
&self.value
}
}
pub fn update(item: &mut Item) {
let value = item.value_mut();
value.change(); // how it changes is unimportant
println!("Updated item: {}", item.name());
}
Now, I know why this fails. I have a mutable reference to item through the mutable reference to the value.
If I convert the reference to an owned String, it works fine, but looks strange to me:
pub fn update(item: &mut Item) {
let name = { item.name().to_owned() };
let value = item.value_mut();
value.change(); // how it changes is unimportant
println!("Updated item: {}", name); // It works!
}
If I let value reference drop, then everything is fine.
pub fn update(item: &mut Item) {
{
let value = item.value_mut();
value.change(); // how it changes is unimportant
}
println!("Updated item: {}", item.name()); // It works!
}
The value.change() block is rather large, and accessing other fields in item might be helpful. So while I do have solutions to this issue, I'm wondering if there is a better (code-smell) way to do this. Any suggestions?
My intention behind the above structs was to allow Items to change values, but the name should be immutable. LockableValue is an tool to interface with another memory system, and copying/cloning the struct is not a good idea, as the memory is managed there. (I implement Drop on LockableValue to clean up.)
I was hoping it would be straight-forward to protect members of the struct from modification (even if it were immutable) like this... and I can, but it ends up looking weird to me. Maybe I just need to get used to it?
You could use interior mutability on only the part that you want to mutate by using a RefCell like ths:
use std::cell::{RefCell, RefMut};
pub struct LockableValue;
impl LockableValue {
fn change(&mut self) {}
}
pub struct Item {
name: String,
value: RefCell<LockableValue>, // another struct that I'd like to mutate
}
impl Item {
pub fn name(&self) -> &str {
&self.name
}
pub fn value_mut(&self) -> RefMut<'_, LockableValue> {
self.value.borrow_mut()
}
}
pub fn update(item: &Item) {
let name = item.name();
let mut value = item.value_mut();
value.change(); // how it changes is unimportant
println!("Updated item: {}", name);
}
That way you only need a shared reference to Item and you don't run into an issue with the borrow checker.
Not that this forces the borrow checks on value to be done at runtime though and thus comes with a performance hit.
I'm making a maze algorithm using rust and wasm and I have two structs. A maze, and maze has an Vec of a Block struct.
Like this:
pub struct Maze {
pub cols: usize,
pub rows: usize,
pub blocks: Vec<Block>,
pub stack: Vec<usize>,
}
impl Maze {
pub fn new(cols: usize, rows: usize) -> Maze {
let mut maze = Maze {
cols,
rows,
blocks: vec![],
};
for y in 0..rows {
for x in 0..cols {
maze.blocks.push(Block::new(x, y))
}
}
maze
}
And the struct Block has an attribute called visited.
I want in a struct function of Maze change this value
// in Maze struct impl
pub fn run(&mut self) {
let current_index = self.get_current_index();
let mut current_block = &mut &self.blocks[current_index];
// .....
*current_block.visited = true;
In the last line occur an error:
error[E0614]: type `bool` cannot be dereferenced
--> src/maze.rs:119:17
|
119 | *current_block.visited = true;
| ^^^^^^^^^^^^^^^^^^^^^^
How can I do to change this value?
This is my implementation of Block
pub struct Block {
pub x: usize,
pub y: usize,
pub visited: bool,
}
impl Block {
pub fn new(x: usize, y: usize) -> Block {
Block {
x,
y,
visited: false,
}
}
How can I do to change the visited value from Maze.run?
There are two problems, one which is the error you see and one which you will encounter next. The problem with
*current_block.visited = true;
is that the precedence of * is lower than ., so you've written code equivalent to)
*(current_block.visited) = true;
which does not compile because the type of the visited field is bool, which indeed cannot be dereferenced. You could write
(*current_block).visited = true;
and that would work, but it's also unnecessary, because in Rust the . operator looks through references, so you only need
current_block.visited = true;
to assign to the visited field of an &mut Block.
The second problem is that you have an extra & here:
let mut current_block = &mut &self.blocks[current_index];
This means current_block is of type &mut &Block. You can never mutate through an & reference, so you need to remove the &, and it is not needed anyway:
let mut current_block = &mut self.blocks[current_index];
I have a situation where I have to move a struct from one object to another through a &mut self. Take a look:
pub struct MyStruct {
//no copy trait
device: Device
}
impl MyStruct {
pub fn finalize(&mut self) {
//error: cannot move since I borrowed
let interface = InterfaceBuilder::new(self.device)
}
}
First of all, why I cannot move something out of a borrowed mutable reference? Borrowed mutables are exclusive, there's no chance another code is looking into it.
Well, to address this problem I changed to
pub struct MyStruct {
//no copy trait
device: RefCell<Device>
}
impl MyStruct {
pub fn finalize(&mut self) {
//error on `self.device`: cannot move out of `self.device` which is behind a mutable reference
let interface = InterfaceBuilder::new(self.device.into_inner())
}
}
I know why the error occurs:
pub fn into_inner(self) -> T
calling into_inner makes self.device move. Why RefCell simply does not have an implementation pub fn into_inner(&mut self) -> T? I don't see a problem.
You cannot move out of a mutable reference because that would leave the original object incomplete.
Consider this code:
struct MyStruct {
s: String
}
fn finalize(f: &mut MyStruct) {
let _x = f.s; //error E0507!
}
fn main() {
let mut my = MyStruct {
s: "hi".into()
};
finalize(&mut my);
println!("{}", my.s); //what should this do?
}
Then, RefCell::into_inner(&mut self) -> T has the same problem. You could call it twice in a row and you would get two T values where before there was only one. And that, for a non Copy type is impossible.
If you want this function to consume the inner value, probably it should consume the outer value too:
fn finalize(f: MyStruct) {
let _x = f.s;
}
If you really want to move a value out of a mutable reference, you must leave something valid in its place. The easiest way is to declare an Option and use take() to steal and replace it with a None:
struct MyStruct {
s: Option<String>
}
fn finalize(f: &mut MyStruct) {
let _x = f.s.take();
}
Naturally, Option::take returns an Option so that if you call it twice, the second time you get None. If you are positive you have a value you can do take().uwnrap().
Alternatively, if your field type is Default you can use std::mem::take that replaces it with a default-created value:
struct MyStruct {
s: Vec<i32>
}
fn finalize(f: &mut MyStruct) {
let _x = std::mem::take(&mut f.s);
}
PS #1: there is Cell::take(&self) -> T, but only if T implements Default. It works just like std::mem::take but with a non-mutable reference.
PS #2: there is also unsafe fn ManuallyDrop::take(slot: &mut ManuallyDrop<T>) -> T, that is intented to be used in advanced drop implementations. But it is unsafe so it should never be your first option: if you call it twice you will get undefined behavior.
I ran into an issue when dealing with nested method calls with &mut receivers that result in borrow checker errors. Specifically, the deal function implemented for the Table struct. The Table has both players: Vec<Player> and a deck: Vec<Card>. During deal, I am attempting to move cards from the Table's deck into Playerss` hands.
struct Card {
value: u32,
}
struct Player {
name: String,
hand: Vec<Card>,
}
struct Table {
players: Vec<Player>,
deck: Vec<Card>,
}
impl Card {
fn new(value: u32) -> Card {
Card { value: value }
}
}
impl Player {
fn new<S>(name: S) -> Player where S: Into<String> {
Player { name: name.into(), hand: Vec::new() }
}
}
impl Table {
fn new(players: Vec<Player>) -> Table {
let deck = vec![
Card::new(0),
Card::new(1),
Card::new(2),
Card::new(3),
Card::new(4),
Card::new(5),
Card::new(6),
Card::new(7),
Card::new(8),
Card::new(9),
];
Table { players: players, deck: deck }
}
fn deal(&mut self) {
for player in &mut self.players {
self.hit(player);
// Table::hit_b(player, &mut self.deck);
// player.hand.push(self.deck.pop().unwrap());
}
}
fn hit(&mut self, player: &mut Player) {
player.hand.push(self.deck.pop().unwrap());
}
fn hit_b(player: &mut Player, deck: &mut Vec<Card>) {
player.hand.push(deck.pop().unwrap());
}
}
fn main() {
println!("Simplified Playing Card Implementation");
// Initialization
let players = vec![
Player::new("Player 1"),
Player::new("Player 2"),
Player::new("Player 3"),
];
let mut table = Table::new(players);
// Action
table.deal();
// Print
for player in &table.players {
print!("{}: ", player.name);
for card in &player.hand {
print!("{} ", card.value);
}
println!("");
}
}
error[E0499]: cannot borrow `*self` as mutable more than once at a time
--> src/main.rs:47:4
|
46 | for player in &mut self.players {
| ------------ first mutable borrow occurs here
47 | self.hit(player);
| ^^^^ second mutable borrow occurs here
48 | // player.hand.push(self.deck.pop().unwrap());
49 | }
| - first borrow ends here
I have implemented several different workarounds, namely direct in-lining and static functions, that are commented out in for the code in question. Of course, there are many other workarounds that I did not include for brevity's sake.
Is there a idiomatic way to approach the problem of nested method calls with &mut receivers? There might be a solution that deals with explicit lifetimes that I am not seeing, but I couldn't quite put a finger on it.
I have also found some relevant issues:
https://github.com/rust-lang/rfcs/issues/811
https://github.com/rust-lang/rust/issues/6268
As an aside, would anyone be privy to whether this design pattern will be addressed in an upcoming Rust release, maybe related to the improvements seen with MIR?
It seems that if you borrow a reference to a struct field, the whole struct is considered borrowed. I've managed to isolate and example of what I want to do. I just want to get a "read-only" reference to a field in B to obtain some data and then modify another field of B. Is there a idiomatic Rust way to do this?
struct A {
i: i32,
}
struct B {
j: i32,
a: Box<A>,
}
impl B {
fn get<'a>(&'a mut self) -> &'a A {
&*self.a
}
fn set(&mut self, j: i32) {
self.j = j
}
}
fn foo(a: &A) -> i32 {
a.i + 1
}
fn main() {
let a = Box::new(A { i: 47 });
let mut b = B { a: a, j: 1 };
let a_ref = b.get();
b.set(foo(a_ref));
}
error[E0499]: cannot borrow `b` as mutable more than once at a time
--> src/main.rs:27:5
|
26 | let a_ref = b.get();
| - first mutable borrow occurs here
27 | b.set(foo(a_ref));
| ^ second mutable borrow occurs here
28 | }
| - first borrow ends here
It's a feature of the language. From the compiler point of view, there is no way for it to know that it's safe to call your set() function while a is borrowed via get().
Your get() function borrows b mutably, and returns a reference, thus b will remain borrowed until this reference goes out of scope.
You have several way of handling this:
Separate your two fields into two different structs
Move the code which needs to access both attribute inside a method of B
Make your attributes public, you will thus be able to directly get references to them
Compute the new value before setting it, like this:
fn main() {
let a = Box::new(A { i: 47 });
let mut b = B { a: a, j: 1 };
let newval = {
let a_ref = b.get();
foo(a_ref)
};
b.set(newval);
}
Expanding a bit on Levans' answer
Move the code which needs to access both attribute inside a method of B
That might look like this at a first pass:
impl B {
fn do_thing(&mut self) {
self.j = self.a.foo()
}
}
However, this hard-codes the call to foo. You could also accept a closure to allow this to be more flexible:
impl B {
fn update_j_with_a<F>(&mut self, f: F)
where
F: FnOnce(&mut A) -> i32,
{
self.j = f(&mut self.a)
}
}
// ...
b.update_j_with_a(|a| a.foo())
Separate your two fields into two different structs
This is also applicable when you have borrowed two disjoint subsets of attributes. For example:
struct A {
description: String,
name: String,
age: u8,
money: i32,
}
impl A {
fn update_description(&mut self) {
let description = &mut self.description;
*description = self.build_description()
// cannot borrow `*self` as immutable because `self.description` is also borrowed as mutable
}
fn build_description(&self) -> String {
format!(
"{} is {} years old and has {} money",
self.name,
self.age,
self.money
)
}
}
fn main() {}
Can be changed into
struct A {
description: String,
info: Info,
}
struct Info {
name: String,
age: u8,
money: i32,
}
impl A {
fn update_description(&mut self) {
let description = &mut self.description;
*description = self.info.build_description()
}
}
impl Info {
fn build_description(&self) -> String {
format!(
"{} is {} years old and has {} money",
self.name,
self.age,
self.money
)
}
}
fn main() {}
You can combine these two steps (and I'd say that it's better practice) and move the method onto the inner struct.