Parent <-> Child relation ownership problem - rust

I'm just starting to learn Rust and I'm having some troubles understanding how ownership works in my case:
use std::ops::IndexMut;
// ================================================
struct Container {
root: Option<ContainerItem>,
items: Vec<ContainerItem>
}
impl Container {
pub fn create_item(&mut self) -> usize {
let item = create_test_item();
let idx = self.items.len();
self.items.push(item);
return idx;
}
pub fn get_item(&mut self, index: usize) -> &mut ContainerItem {
return self.items.index_mut(index);
}
pub fn new() -> Container {
let mut x = Container {
root: None,
items: Vec::new()
};
x.root = Some(create_test_item());
return x;
}
}
// ================================================
struct ContainerItem {
idx: usize,
children: Vec<usize>,
parent: usize,
has_parent: bool
}
impl ContainerItem {
pub fn add_child(&mut self, value: &mut ContainerItem) {
value.parent = self.idx;
value.has_parent = true;
self.children.push(value.idx);
}
}
// ================================================
fn create_test_item() -> ContainerItem {
ContainerItem {
idx: 1,
children: Vec::new(),
parent: 0,
has_parent: false
}
}
fn main() {
let mut container = Container::new();
let item_index = container.create_item();
let item = container.get_item(item_index);
if let Some(mut root) = container.root {
root.add_child(item);
}
}
I have a Container, with ContainerItems. Each ContainerItem can have children and also has a reference to its parent (both children and the parent are stored as their index in Container's items vec). This is all fine, adding items to the container works, but when I try to add a child to Container's root item (which is a ContainerItem), it throws errors:
error[E0503]: cannot use `container.root` because it was mutably borrowed
--> src/main.rs:68:12
|
66 | let item = container.get_item(item_index);
| --------- borrow of `container` occurs here
67 |
68 | if let Some(mut root) = container.root {
| ^^^^^^^^^^^^^^ use of borrowed `container`
69 | root.add_child(item);
| ---- borrow later used here
error[E0505]: cannot move out of `container.root.0` because it is borrowed
--> src/main.rs:68:17
|
66 | let item = container.get_item(item_index);
| --------- borrow of `container` occurs here
67 |
68 | if let Some(mut root) = container.root {
| ^^^^^^^^ move out of `container.root.0` occurs here
69 | root.add_child(item);
| ---- borrow later used here
If I change the call to add_child to use for e.g. create_test_item() as the argument, then it works fine.
I assume this might be because Container's items field has ownership over all ContainerItems? But I'm passing it by reference to add_child so I think this shouldn't matter, since I'm not changing the owner?

I think the trouble comes from the fact that in this Parent ←→ Child relation the items are sometimes referred to with references and sometimes with indices.
So, it is not always clear when the borrow should concern the container as a whole or just one item which is a part of it.
Moreover, the root item is not stored in the same place as the other items so no index can be used to refer to it.
I reorganised your code in order to always rely on indices (as far I understand your intention; maybe it is not always equivalent to what you wanted initially).
This way, as soon we have to adjust many indices, we just borrow the container as a whole.
Consequently, the add_child() method is moved from the item implementation to the container.
Note that the has_parent boolean was also a good opportunity to switch to Option.
Note also that, as long as we borrow an item with get_item() or get_item_mut(), we cannot create new items because the reallocation inside the Vec could invalidate the references; the borrow-checker will forbid that.
pub struct Container {
root: Option<usize>, // why not implicitly alway 0?
items: Vec<ContainerItem>,
}
impl Container {
pub fn create_item(&mut self) -> usize {
let idx = self.items.len();
let item = create_test_item(idx);
self.items.push(item);
idx
}
pub fn get_item(
&self,
index: usize,
) -> &ContainerItem {
&self.items[index]
}
pub fn get_item_mut(
&mut self,
index: usize,
) -> &mut ContainerItem {
&mut self.items[index]
}
pub fn new() -> Container {
let mut this = Container {
root: None,
items: Vec::new(),
};
this.root = Some(this.create_item());
this
}
pub fn add_child(
&mut self,
parent_idx: usize,
child_idx: usize,
) {
// forget child in previous parent if any
if let Some(prev_parent_idx) = self.items[child_idx].parent {
let prev_children = &mut self.items[prev_parent_idx].children;
let idx = prev_children.iter().position(|i| *i == child_idx);
prev_children.remove(idx.unwrap());
}
// give the child its new parent
let child = &mut self.items[child_idx];
child.parent = Some(parent_idx);
// append this new child to the parent
let parent = &mut self.items[parent_idx];
parent.children.push(child_idx);
}
}
#[derive(Debug)]
pub struct ContainerItem {
idx: usize,
children: Vec<usize>,
parent: Option<usize>,
}
fn create_test_item(idx: usize) -> ContainerItem {
ContainerItem {
idx,
children: Vec::new(),
parent: None,
}
}
fn main() {
let mut container = Container::new();
let item_idx = container.create_item();
println!("item: {:?}", container.get_item(item_idx));
if let Some(root_idx) = container.root {
println!("root: {:?}", container.get_item(root_idx));
println!("~~~~~~~~");
container.add_child(root_idx, item_idx);
println!("item: {:?}", container.get_item(item_idx));
println!("root: {:?}", container.get_item(root_idx));
}
}

let item = container.get_item(item_index);
if let Some(mut root) = container.root {
root.add_child(item);
}
container.get_item has already borrowed a value from &self. Therefore root.add_child will be restricted as long as that borrow exists.
Since the goal is simply to add an element to vec, there is no need to even have the attribute root: Option<ContainerItem>. By default when a new container is created, items can be an empty vector and when there is an item to be added it can be pushed to the vector.
Here is a simple way to implement the parent-child relationship
struct Parent<'a> {
children: &'a mut Vec<Child>,
}
impl Parent<'_> {
pub fn add(&mut self, c: Child) -> () {
let root = &mut self.children;
root.push(c)
}
pub fn get_item(
&self,
index: usize,
) -> &Child {
&self.children[index]
}
}
struct Child {
i: i32,
}
fn main() {
let c1 = Child { i: 1 };
let mut data = vec![c1];
let c12 = Child { i: 1 };
data.push(c12);
let mut p = Parent { children: &mut data };
let c12 = Child { i: 2 };
p.add(c12);
let item = p.get_item(2);
println!("{}", item.i) //2
Obviously other traits can be added to the parent

Related

Cannot borrow `*self` as mutable more than once at a time when using an iterator

I'm trying to learn rust making a game with SDL2. I have a struct GameEngine which has ownership of some variables to control the game state.
The method GameEngine::run() is responsible to manage the game loop. I want this method to do 2 things:
Check if some event is related to closing the game and in this case break the loop
For any other kind of event I want to call a method GameEngine::handle_event() to handle it
The problem is that the compiler is refusing to accept my code telling me I'm trying to borrow self as mutable more than once. The first borrow happen on this line:
let event_poll_iterator = self.event_pump.poll_iter();
and the second on this:
self.handle_event(event);
As I'm a newbie in Rust, I'm getting stuck in this error.
The complete code:
pub mod engine {
use std::time::Duration;
use sdl2::{EventPump, Sdl};
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::pixels::Color;
use sdl2::render::WindowCanvas;
fn get_canvas(sdl_context: &Sdl) -> WindowCanvas {
let video_subsystem = sdl_context.video().unwrap();
let window = video_subsystem
.window("SDL2 Snake Game", 800, 600)
.position_centered()
.opengl()
.build()
.map_err(|e| e.to_string()).unwrap();
let mut canvas = window.into_canvas().build().map_err(|e| e.to_string()).unwrap();
canvas.set_draw_color(Color::BLACK);
canvas
}
pub struct GameEngine {
context: Sdl,
event_pump: EventPump,
canvas: WindowCanvas,
}
impl GameEngine {
pub fn new() -> Self {
let context = sdl2::init().unwrap();
let canvas = get_canvas(&context);
let event_pump = context.event_pump().unwrap();
GameEngine { context, canvas, event_pump }
}
fn redraw(&mut self) {
self.canvas.clear();
self.canvas.present();
}
fn handle_event(&mut self, event: Event) {
todo!()
}
pub fn run(&mut self) {
'game_loop: loop {
let event_poll_iterator = self.event_pump.poll_iter();
for event in event_poll_iterator {
match event {
Event::Quit { .. }
| Event::KeyDown {
keycode: Some(Keycode::Escape),
..
} => break 'game_loop,
_ => {
self.handle_event(event);
}
}
}
self.redraw();
std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 30));
}
}
}
}
Edit
I could reproduce the same problem (I think) with a much smaller example:
struct List {
v: Vec<u32>
}
impl List {
fn increment(&mut self, x: &mut u32) {
*x += 1;
}
fn iter(&mut self) {
for x in &mut self.v {
self.increment(x);
}
}
}
fn main() {
let mut list = List { v: vec![1, 2, 3] };
list.iter();
assert!(list.v == vec![2, 3, 4]);
}
Error log:
λ cargo run
Compiling rustlings v4.7.1 (/home/luizalabs/repositories/rust/rustlings)
error[E0499]: cannot borrow `*self` as mutable more than once at a time
--> src/main.rs:12:13
|
11 | for x in &mut self.v {
| -----------
| |
| first mutable borrow occurs here
| first borrow later used here
12 | self.increment(x);
| ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
For more information about this error, try `rustc --explain E0499`.
error: could not compile `rustlings` due to previous error
The problem is, self.handle_event could modify whatever you are iterating over (in this case event_poll_iterator). If you are modifying what the iterator is iterating over, you might want to consider cloning the iterator. If self.handle_event isn't modifying the iterator, you have to show the borrow checker that you are not modifying the iterator. One option is to inline self.handle_event. Another option is to pass whatever you are modifying as mutable to self.handle_event. Here is a simple example of what is going on:
#[derive(Debug)]
struct Point {
x: i32,
y: i32
}
struct Points {
points: Vec<Point>,
num_points: usize
}
impl Points {
fn bar(&mut self, point: &mut Point) {
println!("{:?}", point)
}
fn foo(&mut self) {
for p in &mut self.points {
self.bar(p);
}
}
}
Inlining would change foo as such:
fn foo(&mut self) {
for p in &mut self.points {
println!("{:?}", p); // modified line
}
}
Tried to simplify your example
fn main() {
let i: i32 = 4326;
let b = i.to_le_bytes();
for i in 0..4 {
println!("{}", b[i]);
}
}
pub struct GameEngine {
event_pump: EventPump,
}
pub struct EventPump {
}
impl EventPump {
pub fn poll_iter(&mut self) -> Vec<i32> {
vec![0, 1, 2]
}
}
impl GameEngine {
pub fn new() -> Self {
GameEngine {
event_pump: EventPump { },
}
}
fn redraw(&mut self) {
}
fn handle_event(&mut self, _event: i32) {
todo!()
}
pub fn run(&mut self) {
loop {
let ep = self.event_pump.poll_iter();
let event_poll_iterator = ep.iter();
for event in event_poll_iterator {
match event {
_ => {
self.handle_event(*event);
}
}
}
self.redraw();
}
}
}
Hope without losing sense. Seems it compiled ok.
It changes Iter to vector instance but I'm not sure if that matters.

Nesting Structs: "borrowed value does not live long enough"

I've been working on creating a Table struct that can resolve to a Val trait object along with other data types (Number implemented as an example) and can be seen in the Rust Playground here. I haven't been able to get past this borrow/lifetime issue but the idea is that Number and Table are both Val objects. However, any attempt to write the object to a String buffer causes a failure in compilation.
What am I doing wrong here? And what is the rationale for the borrow checker to operate in this way?
use std::fmt;
use std::fmt::Write;
struct Number(f64);
struct Table<'a> {
rows: Vec<Row<'a>>
// Will have column vector as a member
}
impl <'a>Table<'a> {
fn new(rows: Vec<Vec<Box<dyn Val>>>) -> Table {
let mut table = Table {
rows: rows.into_iter().map(|r| {
Row {
parent: std::ptr::null_mut(),
cells: r
}
}).collect()
};
let parent = &mut table as *mut Table;
table.rows = table.rows.into_iter().map(|mut r| {
r.parent = parent;
r
}).collect();
table
}
}
struct Row<'a> {
parent: *mut Table<'a>,
cells: Vec<Box<dyn Val<'a>>>
}
impl <'a>Row<'a> {
fn to_str(&'a self, buf: &mut String) -> fmt::Result {
let mut cell_iter = self.cells.iter().enumerate().peekable();
let _parent = unsafe { self.parent.as_ref() }; // Real implementation will need parent ref
while let Some((idx,_c)) = cell_iter.next() { // Real implementation will cycle through columns in parent struct
match self.cells.get(idx) {
Some(v) => v.to_str(buf),
None => Ok(())
}?;
if let Some(_) = cell_iter.peek() {
write!(buf, ",")?;
}
}
Ok(())
}
}
pub trait Val<'a> {
fn to_str(&'a self, buf: &mut String) -> fmt::Result;
}
pub trait ObjWriter<'a> {
fn to_str(&'a self, buf: &'a mut String) -> fmt::Result;
}
impl <'a>ObjWriter<'a> for dyn Val<'a> {
fn to_str(&'a self, buf: &mut String) -> fmt::Result { self.to_str(buf) }
}
impl <'a>Val<'a> for Table<'a> {
fn to_str(&'a self, buf: &mut String) -> fmt::Result {
write!(buf, "(START TABLE:")?;
let mut row_iter = self.rows.iter().peekable();
while let Some(r) = row_iter.next() {
r.to_str(buf)?;
write!(buf, "\n")?;
}
write!(buf, "END TABLE)")
}
}
impl Number {
fn to_str(&self, buf: &mut String) -> fmt::Result {
write!(buf,"{}",self.0)
}
}
impl <'a>Val<'a> for Number {
fn to_str(&self, buf: &mut String) -> fmt::Result {
self.to_str(buf)
}
}
fn main() {
let table = Table::new(vec![
vec![Box::new(Number(0.5)),Box::new(Table::new(Vec::new()))],
vec![Box::new(Table::new(Vec::new())),Box::new(Number(0.5))],
]);
let mut buf = String::new();
table.to_str(&mut buf);
println!("{}",buf)
}
error[E0597]: `table` does not live long enough
--> src/main.rs:98:5
|
92 | let table = Table::new(vec![
| ____________________________-
93 | | vec![Box::new(Number(0.5)),Box::new(Table::new(Vec::new()))],
94 | | vec![Box::new(Table::new(Vec::new())),Box::new(Number(0.5))],
95 | | ]);
| |_____- cast requires that `table` is borrowed for `'static`
...
98 | table.to_str(&mut buf);
| ^^^^^ borrowed value does not live long enough
99 | println!("{}",buf)
100 | }
| - `table` dropped here while still borrowed
I did as suggested trentcl, noting that my pointers would be invalidated on move, I refactored my code so that any Row methods would take the parent table's reference as the first parameter. Then I removed all the <'a> followed the compiler errors until it worked.
So the whole problem was allowing the lifetimes to get out of control and using unsafe methods to get parent references. Go figure...

Dereferencing boxed struct and moving its field causes it to be moved

Dereferencing a boxed struct and moving its field causes it to be moved, but doing it in another way works just fine. I don't understand the difference between these two pop functions. How does one fail when the other one doesn't?
pub struct Stack<T> {
head: Option<Box<Node<T>>>,
len: usize,
}
struct Node<T> {
element: T,
next: Option<Box<Node<T>>>,
}
impl<T> Stack<T> {
pub fn pop(&mut self) -> Option<T> {
self.head.take().map(|boxed_node| {
let node = *boxed_node;
self.head = node.next;
node.element
})
}
pub fn pop_causes_error(&mut self) -> Option<T> {
self.head.take().map(|boxed_node| {
self.head = (*boxed_node).next;
(*boxed_node).element
})
}
}
error[E0382]: use of moved value: `boxed_node`
--> src/main.rs:22:13
|
21 | self.head = (*boxed_node).next;
| ------------------ value moved here
22 | (*boxed_node).element
| ^^^^^^^^^^^^^^^^^^^^^ value used here after move
|
= note: move occurs because `boxed_node.next` has type `std::option::Option<std::boxed::Box<Node<T>>>`, which does not implement the `Copy` trait
You can only move out of a box once:
struct S;
fn main() {
let x = Box::new(S);
let val: S = *x;
let val2: S = *x; // <-- use of moved value: `*x`
}
In the first function, you moved the value out of the box and assigned it to the node variable. This allows you to move different fields out of it. Even if one field is moved, other fields are still available. Equivalent to this:
struct S1 {
a: S2,
b: S2,
}
struct S2;
fn main() {
let x = Box::new(S1 { a: S2, b: S2 });
let tmp: S1 = *x;
let a = tmp.a;
let b = tmp.b;
}
In the second function, you move the value to the temporary (*boxed_node) and then move a field out of it. The temporary value is destroyed immediately after the end of the expression, along with its other fields. The box doesn't have the data anymore, and you don't have a variable to take the other field from. Equivalent to this:
struct S1 {
a: S2,
b: S2,
}
struct S2;
fn main() {
let x = Box::new(S1 { a: S2, b: S2 });
let tmp: S1 = *x;
let a = tmp.a;
let tmp: S1 = *x; // <-- use of moved value: `*x`
let b = tmp.b;
}
Some good news is that non-lexical lifetimes will allow your original code to work:
pub struct Stack<T> {
head: Option<Box<Node<T>>>,
len: usize,
}
struct Node<T> {
element: T,
next: Option<Box<Node<T>>>,
}
impl<T> Stack<T> {
pub fn pop_no_longer_causes_error(&mut self) -> Option<T> {
self.head.take().map(|boxed_node| {
self.head = (*boxed_node).next;
(*boxed_node).element
})
}
}
NLL enhances the borrow checker to better track the moves of variables.

match + RefCell = X does not live long enough

I need to initialize an item (fn init(&mut self) -> Option<&Error>), and use it if there's no errors.
pub fn add(&mut self, mut m: Box<Item>) {
if let None = m.init() {
self.items.push(m);
}
}
This works unless I need to check the error if there's any:
pub fn add(&mut self, mut m: Box<Item>) {
if let Some(e) = m.init() {
//process error
} else {
self.items.push(m); //won't compile, m is borrowed
}
}
Fair. Need to use RefCell. However, this
pub fn add(&mut self, mut m: Box<Item>) {
let rc = RefCell::new(m);
if let Some(e) = rc.borrow_mut().init() {
//process error
} else {
self.items.push(rc.borrow_mut())
}
}
ends with weird
error: `rc` does not live long enough
if let Some(e) = rc.borrow_mut().init() {
^~
note: reference must be valid for the destruction scope surrounding block at 75:60...
pub fn add_module(&mut self, mut m: Box<RuntimeModule>) {
^
note: ...but borrowed value is only valid for the block suffix following statement 0 at 76:30
let rc = RefCell::new(m);
I tried nearly everything: plain box, Rc'ed box, RefCell'ed box, Rc'ed RefCell. Tried to adapt this answer to my case. No use.
Complete example:
use std::cell::RefCell;
use std::error::Error;
trait Item {
fn init(&mut self) -> Option<&Error>;
}
struct ItemImpl {}
impl Item for ItemImpl {
fn init(&mut self) -> Option<&Error> {
None
}
}
//===========================================
struct Storage {
items: Vec<Box<Item>>,
}
impl Storage {
fn new() -> Storage {
Storage{
items: Vec::new(),
}
}
fn add(&mut self, mut m: Box<Item>) {
let rc = RefCell::new(m);
if let Some(e) = rc.borrow_mut().init() {
//process error
} else {
self.items.push(*rc.borrow_mut())
}
}
}
fn main() {
let mut s = Storage::new();
let mut i = Box::new(ItemImpl{});
s.add(i);
}
(Playground)
UPD: As suggested, this is a "family" of mistakes like I did, it is well explained here. However my case has easier solution.
As krdln suggested, the simplest way to work around this is to return in the if block and thus scope the borrow:
fn add(&mut self, mut m: Box<Item>) {
if let Some(e) = m.init() {
//process error
return;
}
self.items.push(m);
}

Calling two member functions that work with different fields at the same time [duplicate]

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.

Resources