I have two structs that depend on each other. In C++ I would do this with pointers, I'm trying to figure out how to do this in Rust. I've tried using Box and Rc so far, I would think since Rc is a reference counter it should be able to handle this, but it's giving me an error.
Here is a simple code example:
struct A {
b : Rc<B>
}
struct B {
a : Option<Rc<A>>
}
fn main() {
let mut b = B {
a : None
};
let a = A {
b: Rc::new(b)
};
b.a = Some(Rc::new(a));
}
Here is the error I get from it:
20 | let mut b = B {
| ----- move occurs because `b` has type `B`, which does not implement the `Copy` trait
...
25 | b: Rc::new(b)
| - value moved here
...
28 | b.a = Some(Rc::new(a));
| ^^^ value partially assigned here after move
What is the correct way to do this type of relationship in Rust?
You shouldn't use Rc::new twice for an object. The correct way is to use Rc::new once, and clone it as needed. What's more, in order to mutate b behind a Rc, you should combine it with RefCell.
use std::cell::RefCell;
use std::rc::Rc;
struct A {
b: Rc<B>,
}
struct B {
a: RefCell<Option<Rc<A>>>,
}
fn main() {
let b = Rc::new(B {
a: RefCell::new(None),
});
let a = Rc::new(A { b: b.clone() });
*b.a.borrow_mut() = Some(a.clone());
assert!(b.a.borrow().is_some());
}
But even you do like this, you still make an memory leak, which is bad. A better way is to use Weak and Rc::new_cyclic to make cycles.
use std::rc::{Rc, Weak};
struct A {
b: Rc<B>,
}
struct B {
a: Weak<A>,
}
fn main() {
let a: Rc<A> = Rc::new_cyclic(|a| A {
b: Rc::new(B { a: a.clone() }),
});
let b: Rc<B> = a.b.clone();
}
This avoids use of cells and memory leak.
This is compiling (this is single threaded example)
use std::cell::RefCell;
use std::rc::Rc;
// make a cycle: struct A owning struct B and struct B owning struct A
struct A {
b : Rc<RefCell<B>>
}
struct B {
a : Option<Rc<RefCell<A>>>
}
fn main() {
// init b with None
let b = Rc::new(RefCell::new(B { a: None }));
// init a with b
let a = Rc::new(RefCell::new(A { b: Rc::clone(&b) }));
// set b.a to a
b.borrow_mut().a = Some(Rc::clone(&a));
}
You use Rc to have mutiple ownership. So that you can both move b to a and then still address it as b and even try change it.
Rc is read only so use RefCell so that you hide the fact that you change things.
There is another example of cycle in Rust book
https://doc.rust-lang.org/book/ch15-06-reference-cycles.html
Related
I'm trying to write a program that generates mathematical expressions and then evaluates them. Expressions can contain primitive operations (plus, minus, etc.) or other sub-expressions that consist of primitive operations.
The problem is that sub-expressions are local for the created expression and won't be needed anywhere else except their parent expression (so, I should not make them static), but I can't move parent expression somewhere, because local sub-expressions considered as dropped even if I move them to the parent expression struct.
Minimal example:
Rust Playground
trait Operation {
fn compute(&self) -> i32;
}
struct SumNumbers {
pub numbers: Vec<i32>,
}
impl Operation for SumNumbers {
fn compute(&self) -> i32 {
let mut result = 0;
for x in &self.numbers {
result += x;
}
result
}
}
struct Expression<'a> {
pub operations: Vec<&'a dyn Operation>,
sub_expr_holder: Vec<Expression<'a>>,
}
// Not working attempt to ensure sub_expr_holder will live longer than operations
// struct Expression<'a, 'b : 'a> {
// pub operations: Vec<&'a dyn Operation>,
// sub_expr_holder: Vec<Expression<'a, 'b>>,
// }
impl Operation for Expression<'_> {
fn compute(&self) -> i32 {
let mut result = 0;
for operation in &self.operations {
result += operation.compute();
}
result
}
}
fn build_single_expression() {
let static_sum2 = SumNumbers {
numbers: vec![1, 1],
};
let static_sum4 = SumNumbers {
numbers: vec![1, 3],
};
let static_sum6 = SumNumbers {
numbers: vec![4, 2],
};
let root_expr = {
let local_expr_sum10 = Expression {
operations: vec![&static_sum4 as &dyn Operation,
&static_sum6 as &dyn Operation],
sub_expr_holder: vec![]
};
let mut root_expr = Expression {
operations: vec![],
sub_expr_holder: vec![local_expr_sum10]
};
root_expr.operations = vec![&root_expr.sub_expr_holder[0], &static_sum2];
// Ideal option would be to keep it immutable:
// let root_expr = Expression {
// operations: vec![&local_expr_sum10, &static_sum2],
// sub_expr_holder: vec![local_expr_sum10]
// };
root_expr
};
let root_expr = &root_expr as &dyn Operation;
let result = root_expr.compute();
assert_eq!(result, 12)
}
The errors I get are:
error[E0597]: `root_expr.sub_expr_holder` does not live long enough
--> src/gep_tools/test.rs:61:38
|
50 | let root_expr = {
| --------- borrow later stored here
...
61 | root_expr.operations = vec![&root_expr.sub_expr_holder[0], &static_sum2];
| ^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
...
70 | };
| - `root_expr.sub_expr_holder` dropped here while still borrowed
Even though I move the local_expr_sum10 into the root_expr, the compiler says it doesn't live long enough to be borrowed from root_expr.operations. It seems the second error explains why:
error[E0505]: cannot move out of `root_expr` because it is borrowed
--> src/gep_tools/test.rs:69:9
|
61 | root_expr.operations = vec![&root_expr.sub_expr_holder[0], &static_sum2];
| ------------------------- borrow of `root_expr.sub_expr_holder` occurs here
...
69 | root_expr
| ^^^^^^^^^
| |
| move out of `root_expr` occurs here
| borrow later used here
As I understand, the compiler assumes that I can move the root_expr.sub_expr_holder out of the root_expr struct and it will be dropped while still borrowed by root_expr.operations.
Is there a way how I can force the compiler to forbid move of root_expr.sub_expr_holder out of the struct and therefore let me borrow it? Or any other approach that will let me borrow the local sub-expressions this way?
Edit:
I want to use references specifically, because there may be a lot primitive expressions which are reused among all the expressions and it would be waste of memory to copy them each time. Also, the sub-expressions can be used in the root expression several times:
root_expr.operations = vec![&root_expr.sub_expr_holder[0], &static_sum2, &root_expr.sub_expr_holder[0]];
This doesn't make a lot of sense in this minimal example, but in my full code arguments can be passed to the sub-expressions, so it makes sense to put them in a single expression several times. So, again, it would be a waste of memory to copy them multiple times.
Someone marked this question as a duplicate of "self-referential struct problem" (it was re-opened since then), but as I said, this is just 1 of my attempts to solve my problem. As it turned out, the actual problem is called "Multiple Ownership" and as Chayim Friedman suggested, it can be solved with Rc.
As a simple conclusion: if you need to use a local struct that will be dropped at the end of the scope, but you can not move it and have to use references, then go with a reference counter.
A good place to read about Rc and multiple ownership is the Rust Book.
My solution:
Rust Playground
use std::rc::Rc;
trait Operation {
fn compute(&self) -> i32;
}
struct SumNumbers {
pub numbers: Vec<i32>,
}
impl Operation for SumNumbers {
fn compute(&self) -> i32 {
let mut result = 0;
for x in &self.numbers {
result += x;
}
result
}
}
struct Expression {
pub operations: Vec<Rc<dyn Operation>>,
}
impl Operation for Expression<> {
fn compute(&self) -> i32 {
let mut result = 0;
for operation in &self.operations {
result += operation.compute();
}
result
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn build_single_expression() {
let static_sum2 = SumNumbers {
numbers: vec![1, 1],
};
let static_sum4 = SumNumbers {
numbers: vec![1, 3],
};
let static_sum6 = SumNumbers {
numbers: vec![4, 2],
};
let root_expr = {
let local_expr_sum10: Rc<dyn Operation> = Rc::new(
Expression {
operations: vec![Rc::new(static_sum4),
Rc::new(static_sum6)]
});
Expression {
operations: vec![Rc::clone(&local_expr_sum10),
Rc::clone(&local_expr_sum10),
Rc::new(static_sum2)],
}
};
let root_expr = &root_expr as &dyn Operation;
let result = root_expr.compute();
assert_eq!(result, 22)
}
}
I'm not sure how good this solution is, but it completely solves my problem, and it should not affect performance.
I am having issues with the borrow checker and temporary values in rust.
I'm hoping to find a solution to this specific problem as well as better learn how to handle this kind of situation in the future. I originally started off with a for_each but ran into issues terminating early.
I considered moving the logic of check_foo into update_foo, however this wouldn't work well for my real world solution; the MRE focuses on the compilation issues vs what I'm trying to achieve in the whole program.
Edit: Is there a way for me to achieve this in a purely functional approach?
I want to iterate over a range of numbers, updating a Vec<Foo> and potentially returning early with a value. Below is a minimal reproducible example of my code with the same errors:
I tried tried implementing as:
fn run<'a>(mut foos: Vec<Foo>) -> Vec<&'a u32> {
let mut bar: Vec<&u32> = vec![];
for num in 0..10 {
for foo in &mut foos {
update_foo(foo);
let checked_foo = check_foo(&foo);
if checked_foo.is_empty() {
bar = checked_foo;
break;
}
}
}
bar
}
/* `fn update_foo` and `fn check_foo` definitions same as below */
but this resulted in:
21 | for foo in &mut foos {
| ^^^^^^^^^ `foos` was mutably borrowed here in the previous iteration of the loop
To overcome this I added the use of Rc and RefCell to allow me to iterate over a reference whilst still being able to mutate:
#[derive(Clone, Debug, PartialEq)]
pub struct Foo {
updated: bool,
}
fn run<'a>(foos: Vec<Rc<RefCell<Foo>>>) -> Vec<&'a u32> {
let mut bar: Vec<&u32> = vec![];
for num in 0..10 {
for foo in &foos {
update_foo(&mut foo.borrow_mut());
let checked_foo = check_foo(&foo.borrow());
if checked_foo.is_empty() {
bar = checked_foo;
break;
}
}
}
bar
}
fn update_foo(foo: &mut Foo) {
foo.updated = true
}
fn check_foo(foo: &Foo) -> Vec<&u32> {
if foo.updated {
vec![&0, &1, &2]
} else {
vec![]
}
}
which results in:
error[E0515]: cannot return value referencing temporary value
--> src/main.rs:33:5
|
26 | let checked_foo = check_foo(&foo.borrow());
| ------------ temporary value created here
...
33 | bar
| ^^^ returns a value referencing data owned by the current function
error[E0515]: cannot return value referencing function parameter `foos`
--> src/main.rs:33:5
|
23 | for foo in &foos {
| ----- `foos` is borrowed here
...
33 | bar
| ^^^ returns a value referencing data owned by the current function
For more information about this error, try `rustc --explain E0515`.
I'm not entirely sure what you plan to do with this, but it seems to me like a few of the references you're using should be owned. Here's what I came up with.
#[derive(Clone, Debug, PartialEq)]
pub struct Foo {
updated: bool,
}
fn run(foos: &mut Vec<Foo>) -> Vec<u32> {
let mut bar: Vec<u32> = vec![];
for num in 0..10 {
for foo in foos.iter_mut() {
update_foo(foo);
let checked_foo = check_foo(&foo);
if checked_foo.is_empty() {
bar = checked_foo;
break;
}
}
}
bar
}
fn update_foo(foo: &mut Foo) {
foo.updated = true
}
fn check_foo(foo: &Foo) -> Vec<u32> {
if foo.updated {
vec![0, 1, 2]
} else {
vec![]
}
}
References should be used when you expect some other struct to own the objects you are referring to, but here you're constructing new vectors with new data, so you should keep the elements owned.
I'm trying to make the following code work:
struct IntHolder {
ints: Vec<i32>,
}
impl IntHolder {
fn special_int(&self) -> Option<i32> {
return None;
}
fn all_ints(&self) -> impl Iterator<Item=&i32> {
return self.special_int().iter().chain(self.ints.iter());
}
}
fn main() {
let tst = IntHolder{ints: vec![0, 1, 2]};
for o in tst.all_ints() {
println!("{}", o)
}
}
But I get this error:
|
10 | return self.special_int().iter().chain(self.ints.iter());
| ------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| returns a value referencing data owned by the current function
| temporary value created here
Oddly enough, if I change the function call to just inline None instead of calling the function that returns an option, it works:
struct IntHolder {
ints: Vec<i32>,
}
impl IntHolder {
fn special_int(&self) -> Option<i32> {
return None;
}
fn all_ints(&self) -> impl Iterator<Item=&i32> {
return None.iter().chain(self.ints.iter());
}
}
fn main() {
let tst = IntHolder{ints: vec![0, 1, 2]};
for o in tst.all_ints() {
println!("{}", o)
}
}
Does anyone know how to make this work, or why it only seems to break when I call a function to generate the option?
(This is toy code to illustrate the problem I'm having. In my actual code, I have a struct which holds a vector of objects, and also sometimes has a special object that can be computed from the other fields. I want to return an iterator that iterates over the special object if it can be computed, and then iterates over all the objects in the vector. I'd also like to avoid having to do heap allocations if I can.)
The problem is that iter takes a reference to the value rather than consuming it, returning an iterator that references a value that belongs to the function.
Try using into_iter() instead:
return self.special_int().into_iter().chain(self.ints.iter());
How to parse some string to most appropriate type?
I know there is .parse::<>() method, but you need to specify type in advance like this:
fn main() {
let val = String::from("54");
assert_eq!(val.parse::<i32>().unwrap(), 54i32);
let val = String::from("3.14159");
assert_eq!(val.parse::<f32>().unwrap(), 3.14159f32);
let val = String::from("Hello!");
assert_eq!(val.parse::<String>().unwrap(), "Hello!".to_string());
}
But I need something like this:
fn main() {
let val = String::from("54");
assert_eq!(val.generic_parse().unwrap(), 54i32); // or 54i16 or 54 u32 or etc ...
let val = String::from("3.14159");
assert_eq!(val.generic_parse().unwrap(), 3.14159f32);
let val = String::from("Hello!");
assert_eq!(val.generic_parse().unwrap(), "Hello!".to_string());
}
Is there an appropriate crate for something like this? I don't want to re-invent the wheel for the umpteenth time.
EDIT
This is what I actually want to do:
struct MyStruct<T> {
generic_val: T,
}
fn main() {
let val = String::from("54");
let b = MyStruct {generic_val: val.parse().unwrap()};
let val = String::from("3.14159");
let b = MyStruct {generic_val: val.parse().unwrap()};
}
Error:
error[E0282]: type annotations needed for `MyStruct<T>`
--> src/main.rs:7:13
|
7 | let b = MyStruct {generic_val: val.parse().unwrap()};
| - ^^^^^^^^ cannot infer type for type parameter `T` declared on the struct `MyStruct`
| |
| consider giving `b` the explicit type `MyStruct<T>`, where the type parameter `T` is specified
You need to base things on the right Enum type and implement FromStr for it. Like this.
#[derive(PartialEq, Debug)]
enum Val {
Isize(isize),
F64(f64),
}
impl core::str::FromStr for Val {
type Err = & 'static str;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match (s.parse::<isize>(), s.parse::<f64>()) {
(Ok(i),_) => Ok(Val::Isize(i)),
(Err(_), Ok(f)) => Ok(Val::F64(f)),
(Err(_), Err(_)) => Err("neither parser worked"),
}
}
}
fn main() {
assert_eq!("34".parse(), Ok(Val::Isize(34)));
assert_eq!("12.3".parse(), Ok(Val::F64(12.3)));
assert!("wrong".parse::<Val>().is_err());
}
Rust is a statically typed language. This means that the compiler needs to know the type of variables at compile time. There are three ways things can go from there:
If your strings are known at compile-time, then you might as well replace them with literal values in your code (eg. "54" → 54).
If you have some other way of knowing at compile time what type a given string should parse to, then you can specify the appropriate type when parsing the string: let a = "54".parse::<i32>().unwrap()
If your strings are only known at run-time and you want to autodetect the type, then you need to use some kind of enumerated value that will store the type alongside the value in your program:
use std::str::FromStr;
enum Value {
I32 (i32),
F32 (f32),
String (String),
}
impl Value {
fn new (s: &str) -> Value {
if let Ok (v) = s.parse::<i32>() {
Value::I32 (v)
} else if let Ok (v) = s.parse::<f32>() {
Value::F32 (v)
} else {
Value::String (s.into())
}
}
}
That way, the rest of your code will have a way of knowing what type was detected and to adjust its processing accordingly.
Consider the following bit of code
use std::{cell::RefCell, rc::Rc};
type NodeRef = Rc<RefCell<_Node>>;
#[derive(Debug)]
struct _Node {
id: usize,
data: Option<NodeRef>,
edges: Vec<NodeRef>,
}
impl _Node {
fn add(&mut self, other: NodeRef) {
println!("at {}", self.id);
self.data = match self.data.take() {
Some(current_data) => {
{
let mut current_data_raw = current_data.borrow_mut();
current_data_raw.id += other.borrow().id;
}
Some(current_data)
}
None => Some(Rc::clone(&other)),
};
for e in &self.edges {
e.borrow_mut().add(Rc::clone(&other));
}
println!("done {}", self.id);
}
}
#[derive(Debug)]
struct Node(NodeRef);
impl Node {
fn new(id: usize) -> Node {
Node(Rc::new(RefCell::new(_Node {
id,
data: None,
edges: vec![],
})))
}
fn add_edge(&self, other: &Node) {
self.0.borrow_mut().edges.push(Rc::clone(&other.0));
}
fn add(&self, other: Self) {
self.0.borrow_mut().add(other.0);
}
}
fn main() {
let a = Node::new(0);
let b = Node::new(1);
let c = Node::new(2);
let d = Node::new(3);
let e = Node::new(4);
let f = Node::new(5);
d.add_edge(&a);
d.add_edge(&b);
e.add_edge(&b);
e.add_edge(&c);
f.add_edge(&d);
f.add_edge(&e);
f.add(Node::new(6));
}
The output generated on running this is
at 5
at 3
at 0
done 0
at 1
done 1
done 3
at 4
at 1
thread 'main' panicked at 'already mutably borrowed: BorrowError', src/libcore/result.rs:1009:5
This creates a graph of the form
F--E--A
\ \
\ B
\ /
D
\
C
I am trying to propagate a value through the entire graph, so it starts from F, and goes to E and D. From E it goes to A and B without any error. Then from D, the runtime panics saying the RefCell constraint for mutable borrows has been broken.
It seems that it is considering the mutable borrow from the previous invocation of the callback with B, however, the mutable borrow (current_data_raw) inside _Node::add has a limited scope, and after the scope ends, I should be allowed to mutably borrow the value again. From the output, when the function is called for node B for the second time, the entire first invocation of the function and not just the mutable borrow scope has exited.
What am I missing here?
What am I missing here?
Your algorithm is broken. You can see this by adding this debugging code inside of the Some arm of the match:
{
let a = current_data.borrow();
let b = other.borrow();
assert_ne!(a.id, b.id);
}
This fails:
thread 'main' panicked at 'assertion failed: `(left != right)`
left: `6`,
right: `6`', src/main.rs:23:25
You are trying to borrow the exact same node twice at the same time.