Get Box Pointer from reference in rust - pointers

Say I have a function like this:
fn foo(item: &FooType) -> Box<FooType>{
Box::new(item)
}
I get the following error:
mismatched types: expected enum FooType, found &FooType
I'm assuming I need to do some reference/boxing and lifetime magic, but as a rust beginner, I'm not 100% sure how to get this working.

I think there is no definitive answer since it depends on what you expect.
If you want to obtain a heap-allocated clone of something you want to keep usable, then cloning in foo1() can help.
A better solution could be to pass a value not a reference, as in foo2(), because this way the call site can decide if a clone is necessary or if moving the original value into the box is enough.
You may also want the box to hold the reference instead of the value, as in foo3(), but this is like a code-smell to me (many indirections that make reasoning about lifetimes very complicated).
#[derive(Debug, Clone)]
struct FooType {
value: usize,
}
fn foo1(item: &FooType) -> Box<FooType> {
Box::new(item.clone())
}
fn foo2(item: FooType) -> Box<FooType> {
Box::new(item)
}
fn foo3(item: &FooType) -> Box<&FooType> {
Box::new(item)
}
fn main() {
let ft_a = FooType { value: 12 };
let bft_a = foo1(&ft_a);
println!("bft_a: {:?}", bft_a);
println!("ft_a: {:?}", ft_a);
println!("~~~~~~~~~~~~~~~~~~");
let ft_b = FooType { value: 34 };
let bft_b = foo2(ft_b);
println!("bft_b: {:?}", bft_b);
// println!("ft_b: {:?}", ft_b); // borrow of moved value: `ft_b`
println!("ft_b is consumed");
println!("~~~~~~~~~~~~~~~~~~");
let ft_c = FooType { value: 56 };
let bft_c = foo2(ft_c.clone());
println!("bft_c: {:?}", bft_c);
println!("ft_c: {:?}", ft_c);
println!("~~~~~~~~~~~~~~~~~~");
let ft_d = FooType { value: 78 };
let bft_d = foo3(&ft_d);
println!("bft_d: {:?}", bft_d);
println!("ft_d: {:?}", ft_d);
}
/*
bft_a: FooType { value: 12 }
ft_a: FooType { value: 12 }
~~~~~~~~~~~~~~~~~~
bft_b: FooType { value: 34 }
ft_b is consumed
~~~~~~~~~~~~~~~~~~
bft_c: FooType { value: 56 }
ft_c: FooType { value: 56 }
~~~~~~~~~~~~~~~~~~
bft_d: FooType { value: 78 }
ft_d: FooType { value: 78 }
*/

The compiler is complaining because in the function's signature you specified Box<FooType> as the return type, and you are giving it a Box<&FooType> when you wrap the ìtem in a Box.
Change the function's signature so that it receives a FooType rather than a reference to it like this:
fn foo(item: FooType) -> Box<FooType>{
Box::new(item)
}

Related

the trait cannot be made into an object in Vec [duplicate]

I wrote a program that has the trait Animal and the struct Dog implementing the trait. It also has a struct AnimalHouse storing an animal as a trait object Box<Animal>.
trait Animal {
fn speak(&self);
}
struct Dog {
name: String,
}
impl Dog {
fn new(name: &str) -> Dog {
return Dog {
name: name.to_string(),
};
}
}
impl Animal for Dog {
fn speak(&self) {
println!{"{}: ruff, ruff!", self.name};
}
}
struct AnimalHouse {
animal: Box<Animal>,
}
fn main() {
let house = AnimalHouse {
animal: Box::new(Dog::new("Bobby")),
};
house.animal.speak();
}
It returns "Bobby: ruff, ruff!" as expected, but if I try to clone house the compiler returns errors:
fn main() {
let house = AnimalHouse {
animal: Box::new(Dog::new("Bobby")),
};
let house2 = house.clone();
house2.animal.speak();
}
error[E0599]: no method named `clone` found for type `AnimalHouse` in the current scope
--> src/main.rs:31:24
|
23 | struct AnimalHouse {
| ------------------ method `clone` not found for this
...
31 | let house2 = house.clone();
| ^^^^^
|
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `clone`, perhaps you need to implement it:
candidate #1: `std::clone::Clone`
I tried to add #[derive(Clone)] before struct AnimalHouse and got another error:
error[E0277]: the trait bound `Animal: std::clone::Clone` is not satisfied
--> src/main.rs:25:5
|
25 | animal: Box<Animal>,
| ^^^^^^^^^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `Animal`
|
= note: required because of the requirements on the impl of `std::clone::Clone` for `std::boxed::Box<Animal>`
= note: required by `std::clone::Clone::clone`
How do I make the struct AnimalHouse cloneable? Is it idiomatic Rust to use a trait object actively, in general?
There are a few problems. The first is that there's nothing to require that an Animal also implements Clone. You could fix this by changing the trait definition:
trait Animal: Clone {
/* ... */
}
This would cause Animal to no longer be object safe, meaning that Box<dyn Animal> will become invalid, so that's not great.
What you can do is insert an additional step. To whit (with additions from #ChrisMorgan's comment).
trait Animal: AnimalClone {
fn speak(&self);
}
// Splitting AnimalClone into its own trait allows us to provide a blanket
// implementation for all compatible types, without having to implement the
// rest of Animal. In this case, we implement it for all types that have
// 'static lifetime (*i.e.* they don't contain non-'static pointers), and
// implement both Animal and Clone. Don't ask me how the compiler resolves
// implementing AnimalClone for dyn Animal when Animal requires AnimalClone;
// I have *no* idea why this works.
trait AnimalClone {
fn clone_box(&self) -> Box<dyn Animal>;
}
impl<T> AnimalClone for T
where
T: 'static + Animal + Clone,
{
fn clone_box(&self) -> Box<dyn Animal> {
Box::new(self.clone())
}
}
// We can now implement Clone manually by forwarding to clone_box.
impl Clone for Box<dyn Animal> {
fn clone(&self) -> Box<dyn Animal> {
self.clone_box()
}
}
#[derive(Clone)]
struct Dog {
name: String,
}
impl Dog {
fn new(name: &str) -> Dog {
Dog {
name: name.to_string(),
}
}
}
impl Animal for Dog {
fn speak(&self) {
println!("{}: ruff, ruff!", self.name);
}
}
#[derive(Clone)]
struct AnimalHouse {
animal: Box<dyn Animal>,
}
fn main() {
let house = AnimalHouse {
animal: Box::new(Dog::new("Bobby")),
};
let house2 = house.clone();
house2.animal.speak();
}
By introducing clone_box, we can get around the problems with attempting to clone a trait object.
My dyn-clone crate implements a reusable version of DK.'s answer. With it you can make your original code work with a bare minimum of changes.
One line to add DynClone as a supertrait of Animal, requiring every animal implementation to be clonable.
One line to generate an implementation of the standard library Clone for Box<dyn Animal>.
// [dependencies]
// dyn-clone = "1.0"
use dyn_clone::{clone_trait_object, DynClone};
trait Animal: DynClone {
fn speak(&self);
}
clone_trait_object!(Animal);
#[derive(Clone)]
struct Dog {
name: String,
}
impl Dog {
fn new(name: &str) -> Dog {
Dog { name: name.to_owned() }
}
}
impl Animal for Dog {
fn speak(&self) {
println!{"{}: ruff, ruff!", self.name};
}
}
#[derive(Clone)]
struct AnimalHouse {
animal: Box<dyn Animal>,
}
fn main() {
let house = AnimalHouse {
animal: Box::new(Dog::new("Bobby")),
};
let house2 = house.clone();
house2.animal.speak();
}
The previous answer correctly answers the question about storing a boxed trait object.
Getting off topic with respect to the title, but not about the idiomatic way of using trait objects, an alternative solution could be use the Rc smart pointer instead of a Box: this avoids the workaround for getting around object safety:
#[derive(Clone)]
struct AnimalHouse {
animal: Rc<Animal>,
}
fn main() {
let house = AnimalHouse { animal: Rc::new(Dog::new("Bobby")) };
let house2 = house.clone();
house2.animal.speak();
}
Note: Rc<T> is only for use in single-threaded scenarios; there's also Arc<T>.

How do I flatten a recursive structure using recursive iterators?

I'm trying to flatten a recursive structure but I'm having trouble with recursive iterators.
Here's what the struct looks like:
#[derive(Debug, Clone)]
pub struct C {
name: String,
vb: Option<Vec<B>>,
}
#[derive(Debug, Clone)]
pub struct B {
c: Option<C>,
}
#[derive(Debug, Clone)]
pub struct A {
vb: Option<Vec<B>>,
flat_c: Option<Vec<C>>,
}
My plan is to traverse the vb vector and flatten it into flat_c. I want it to look like this, or at least, be a Vec<String>:
Some([
C {
name: "foo",
vb: None,
},
C {
name: "bar",
vb: None,
},
C {
name: "fizz",
vb: None,
},
C {
name: "buzz",
vb: None,
},
])
Here what I managed to do, somewhat flattening the struct, but only for the last element, as the recursion is not implemented.
impl A {
fn flat_c(self) -> Self {
let fc: Vec<C> = self
.vb
.clone()
.unwrap()
.iter()
.flat_map(|x| x.c.as_ref().unwrap().vb.as_ref().unwrap().iter())
.cloned()
.map(|x| x.c.unwrap())
.collect();
Self {
flat_c: Some(fc),
..self
}
}
}
fn main() {
let a = A {
vb: Some(vec![
B {
c: Some(C {
name: "foo".to_string(),
vb: Some(vec![B {
c: Some(C {
name: "bar".to_string(),
vb: None,
}),
}]),
}),
},
B {
c: Some(C {
name: "fiz".to_string(),
vb: Some(vec![B {
c: Some(C {
name: "buzz".to_string(),
vb: None,
}),
}]),
}),
},
]),
flat_c: None,
};
let a = a.flat_c();
println!("a: {:#?}", a);
}
playground
The output for flat_c:
Some([
C {
name: "bar",
vb: None,
},
C {
name: "buzz",
vb: None,
},
])
I haven't dived into the Iterator trait implementation that might be required for this problem.
How would I tackle this problem? Maybe using a fold? Perhaps a recursive approach is not even needed? I'm at loss.
It's a good idea to be familiar with common data structures. You have a tree, and there are several ways to traverse a tree. You haven't precisely specified which method to use, so I chose one arbitrarily that's easy to implement.
The key here is to implement an iterator that keeps track of some state: all of the nodes yet to be visited. On each call to Iterator::next, we take the next value, save aside any new nodes to visit, and return the value.
Once you have the iterator, you can collect it into a Vec.
use std::collections::VecDeque;
impl IntoIterator for A {
type IntoIter = IntoIter;
type Item = String;
fn into_iter(self) -> Self::IntoIter {
IntoIter {
remaining: self.vb.into_iter().flatten().collect(),
}
}
}
struct IntoIter {
remaining: VecDeque<B>,
}
impl Iterator for IntoIter {
type Item = String;
fn next(&mut self) -> Option<Self::Item> {
self.remaining.pop_front().and_then(|b| {
b.c.map(|C { name, vb }| {
self.remaining.extend(vb.into_iter().flatten());
name
})
})
}
}
fn to_strings(a: A) -> Vec<String> {
a.into_iter().collect()
}
#[derive(Debug, Clone)]
struct A {
vb: Option<Vec<B>>,
}
#[derive(Debug, Clone)]
struct B {
c: Option<C>,
}
#[derive(Debug, Clone)]
struct C {
name: String,
vb: Option<Vec<B>>,
}
fn main() {
let example: A = A {
vb: Some(vec![
B {
c: Some(C {
name: "Hello ".to_string(),
vb: None,
}),
},
B {
c: Some(C {
name: "World!".to_string(),
vb: None,
}),
},
]),
};
println!("The example struct: {:?}", example);
//clone a copy for a second example, because to_strings() takes ownership of the example A struct
let receipt: A = example.clone();
println!("Iterated: {:?}", to_strings(example));
// another example of using to_strings()
println!(
"As a string: {:?}",
to_strings(receipt).into_iter().collect::<String>()
);
}
From here, it should be straight-forward to create an iterator of B if that's what you need. Having all of the None values seemed silly, so I left them out and directly returned Strings.
I also made this a by-value iterator. You could follow the same pattern to create an iterator that returned references to the B / String and only clone them as needed.
See also:
How to implement Iterator and IntoIterator for a simple struct?
Implement IntoIterator for binary tree
Cannot obtain a mutable reference when iterating a recursive structure: cannot borrow as mutable more than once at a time
Recursive inorder traversal of a binary search tree
There is my solution:
impl C {
fn flat(&self) -> Vec<C> {
let mut result = Vec::new();
result.push(C {
name: self.name.clone(),
vb: None,
});
if self.vb.is_some() {
result.extend(
(self.vb.as_ref().unwrap().iter())
.flat_map(|b| b.c.as_ref().map(|c| c.flat()).unwrap_or(Vec::new())),
);
}
return result;
}
}
impl A {
fn flat_c(self) -> Self {
let fc = (self.vb.as_ref().unwrap().iter())
.flat_map(|b| b.c.as_ref().unwrap().flat())
.collect();
Self {
flat_c: Some(fc),
..self
}
}
}
It adds flat function for C because the C is the source of the recursion and only this struct may properly handle it.
Because of those Options it looks scary and there is hard to deal with cryptic error messages. This solution supposes that all b.cs of initial a is not a None. Otherwise, it will panic. My advice is to avoid using Option<Vec> and use just empty vector instead of None.
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=09ea11342cdd733b03172c0fc13c85fd
I'm not sure what exactly you want the result of "traverse the vb vector and flatten it into flat_c" to be, but here's a slightly simpler example of flattening a recursive structure, using once for the value that corresponds to the current node, chain to concatenate it with its children and flat_map to flatten everything:
use std::iter::once;
#[derive(Debug)]
struct S {
name: String,
children: Vec<S>,
}
impl S {
fn flat(self) -> Vec<String> {
once(self.name)
.chain(self.children.into_iter().flat_map(|c| c.flat()))
.collect()
}
}
fn main() {
let s = S {
name: "parent".into(),
children: vec![
S {
name: "child 1".into(),
children: vec![],
},
S {
name: "child 2".into(),
children: vec![],
},
],
};
println!("s: {:?}", s);
println!("flat: {:?}", s.flat());
}
playground

How do I return a vector element from a Rust function?

I would like to return an element of a vector:
struct EntryOne {
pub name: String,
pub value: Option<String>,
}
struct TestVec {}
impl TestVec {
pub fn new() -> TestVec {
TestVec {}
}
pub fn findAll(&self) -> Vec<EntryOne> {
let mut ret = Vec::new();
ret.push(EntryOne {
name: "foo".to_string(),
value: Some("FooVal".to_string()),
});
ret.push(EntryOne {
name: "foo2".to_string(),
value: Some("FooVal2".to_string()),
});
ret.push(EntryOne {
name: "foo3".to_string(),
value: None,
});
ret.push(EntryOne {
name: "foo4".to_string(),
value: Some("FooVal4".to_string()),
});
ret
}
pub fn findOne(&self) -> Option<EntryOne> {
let mut list = &self.findAll();
if list.len() > 0 {
println!("{} elements found", list.len());
list.first()
} else {
None
}
}
}
fn main() {
let test = TestVec::new();
test.findAll();
test.findOne();
}
(playground)
I always get this error:
error[E0308]: mismatched types
--> src/main.rs:40:13
|
35 | pub fn findOne(&self) -> Option<EntryOne> {
| ---------------- expected `std::option::Option<EntryOne>` because of return type
...
40 | list.first()
| ^^^^^^^^^^^^ expected struct `EntryOne`, found &EntryOne
|
= note: expected type `std::option::Option<EntryOne>`
found type `std::option::Option<&EntryOne>`
How do I return an element?
Look at the signature for Vec::first:
fn first(&self) -> Option<&T>
Given a reference to a vector, it will return a reference to the first item if there is one, and None otherwise. That means that the vector containing the values must outlive the return value, otherwise the reference would point to undefined memory.
There are two main avenues:
If you cannot change the vector, then you will need to make a copy of your data structure. The easiest way to do this is to annotate the structure with #[derive(Clone)]. Then you can call Option::cloned on the result of first.
If you can change the vector, then you can remove the first value from it and return it. There are many ways of doing this, but the shortest code-wise is to use the drain iterator.
#[derive(Debug, Clone)]
struct EntryOne {
name: String,
value: Option<String>,
}
fn find_all() -> Vec<EntryOne> {
vec![
EntryOne {
name: "foo".to_string(),
value: Some("FooVal".to_string()),
},
EntryOne {
name: "foo2".to_string(),
value: Some("FooVal2".to_string()),
},
EntryOne {
name: "foo3".to_string(),
value: None,
},
EntryOne {
name: "foo4".to_string(),
value: Some("FooVal4".to_string()),
},
]
}
fn find_one_by_clone() -> Option<EntryOne> {
find_all().first().cloned()
}
fn find_one_by_drain() -> Option<EntryOne> {
let mut all = find_all();
let mut i = all.drain(0..1);
i.next()
}
fn main() {
println!("{:?}", find_one_by_clone());
println!("{:?}", find_one_by_drain());
}
Additional changes:
There's no need for TestVec if there's no state; just make functions.
Rust style is snake_case for method and variable names.
Use vec! to construct a vector when providing all the elements.
Derive Debug so you can print the value.
If you wanted to always get the last element, you can use pop:
fn find_one_by_pop() -> Option<EntryOne> {
find_all().pop()
}

Change borrowed value when modifying original value

First of all, here is a simplified version of my code I'm working on:
struct Object {
size: f32
}
impl Object {
fn on_event(&mut self) {
self.size += 1.0;
println!("Object notified. New size: {}.", self.size);
}
}
struct Manager<'a> {
objects: Vec<&'a mut Object>
}
impl<'a> Manager<'a> {
fn add(&mut self, obj: &'a mut Object) {
self.objects.push(obj);
}
fn notify_objects(&mut self) {
for i in range(0u, self.objects.len()) {
let ref mut obj = *self.objects.get_mut(i);
obj.on_event();
}
}
}
fn main() {
let mut obj1 = Object { size: 1.0 };
let mut obj2 = Object { size: 2.0 };
let mut obj3 = Object { size: 3.0 };
let mut manager = Manager { objects: Vec::new() };
manager.add(&mut obj1);
manager.add(&mut obj2);
manager.add(&mut obj3);
obj1.size = 25.0;
println!("before {}", obj1.size); // should print 25
manager.notify_objects();
println!("after {}", obj1.size); should print 26
}
So I like to create mutable Objects and add them to the Manager, but I should be able to modify the original Objects like shown in the code.
Just FYI, although the accepted answer is totally correct, you'll probably encounter many situations where it's not as convenient as simple mutable-borrow-back-from-owner to access an object from another location.
For example, if you're doing some kind of observer pattern where one location is using an object, and somewhere separate is watching the object for state changes and running something if it changes.
In those situations you're probably best off using RefCell (http://doc.rust-lang.org/std/cell/struct.RefCell.html); you can own references to an object in multiple places, and 'try_borrow()' to get a temporary instance to look at in a specific sub scope.
In your example that's perhaps overkill, but as you hit more complex situations, that's the general solution for having 'multiple references' to an object.
Your code does not compile with errors like this:
<anon>:38:5: 38:21 error: cannot assign to `obj1.size` because it is borrowed
<anon>:38 obj1.size = 25.0;
^~~~~~~~~~~~~~~~
<anon>:34:22: 34:26 note: borrow of `obj1.size` occurs here
<anon>:34 manager.add(&mut obj1);
The problem is, you can't modify an object which has been borrowed (that's exactly the semantics of "borrow" word, isn't it?). When you take a mutable reference of obj1 and put it into the structure, you're effectively blocking all access to obj1 until this mutable reference goes out of scope. But because it haven't done that yet when you're trying to reassign obj1.size, you're getting this error.
This does work:
fn main() {
let mut obj1 = Object { size: 25.0 };
let mut obj2 = Object { size: 2.0 };
let mut obj3 = Object { size: 3.0 };
obj1.size = 25.0;
println!("before {}", obj1.size); // should print 25
{
let mut manager = Manager { objects: Vec::new() };
manager.add(&mut obj1);
manager.add(&mut obj2);
manager.add(&mut obj3);
manager.notify_objects();
}
println!("after {}", obj1.size); // should print 26
}
Here manager appears in its own scope. Because that scope is strictly between accesses to obj1, it works fine.
If you absolutely must access these data while it is borrowed, you have to go through the structure itself:
fn main() {
let mut obj1 = Object { size: 1.0 };
let mut obj2 = Object { size: 2.0 };
let mut obj3 = Object { size: 3.0 };
let mut manager = Manager { objects: Vec::new() };
manager.add(&mut obj1);
manager.add(&mut obj2);
manager.add(&mut obj3);
{
let obj1 = manager.objects.get_mut(0); // returns mutable reference
obj1.size = 25.0;
println!("before {}", obj1.size); // should print 25
}
manager.notify_objects();
{
let obj1 = manager.objects.get(0); // returns immutable reference
println!("after {}", obj1.size); // should print 26
}
}

modifying a field while pattern matching on it

I tried my hands at Rust for the first time today (writing a XML tokenizer), and naturally don’t understand everything:
I have a struct with field that can take an enum value:
enum State { Outside, InATag(~str) }
struct Tokenizer { state: State }
In a impl Tokenizer, I want to match on the current state, and change it in some cases, however this always gives a use of moved value error.
H to access and/or declare the state field so that I can match on it and change its value inside a match branch?
Sorry for the confusion, I meant to change the Tokenizer’s state field, not the state’s String field!
match self.state {
InATag(name) => self.state = Outside,
Outside => ()
}
Without a more concrete example, it is hard to tell whether this would solve your problem, but you can use ref within a match pattern to make a reference to the matched substructure, and you can use ref mut to make that reference mutable.
So, in your example:
enum State { Outside, InATag(~str) }
struct Tokenizer { state: State }
fn main() {
let mut t = Tokenizer { state: InATag(~"foo") };
match t.state {
InATag(ref mut _s) => { *_s = ~"bar"; }
Outside => { /* impossible */ }
}
io::println(fmt!("Hello World: %?", t));
}
or if you need to match other parts of the Tokenizer state, this works too:
fn main() {
let mut t = Tokenizer { state: InATag(~"foo") };
match t {
Tokenizer { state: InATag(ref mut _s) } => { *_s = ~"bar"; }
Tokenizer { state: Outside } => { /* impossible */ }
}
io::println(fmt!("Hello World: %?", t));
}
Note that when doing this sort of code, it can be pretty easy to inadvertently run into borrow-check violations due to aliasing. For example, here is a relatively small change to the second example above that won't compile:
fn main() {
let mut t = Tokenizer { state: InATag(~"foo") };
match &t {
&Tokenizer { state: InATag(ref mut _s) } => { *_s = ~"bar"; }
&Tokenizer { state: Outside } => { /* impossible */ }
}
io::println(fmt!("Hello World: %?", t));
}
causes the following message from rustc:
/tmp/m.rs:7:35: 7:46 error: illegal borrow: creating mutable alias to enum content
/tmp/m.rs:7 &Tokenizer { state: InATag(ref mut _s) } => { *_s = ~"bar"; }
^~~~~~~~~~~
error: aborting due to previous error
because you do not want an outstanding borrow &t while you are also creating mutable aliases to the internals of t
Okay, with the clarified variant of the question, here is my revised answer:
enum State { Outside, InATag(~str) }
struct Tokenizer { state: State }
impl Tokenizer {
fn toggle(&mut self) {
match self {
&Tokenizer { state: InATag(*) } => { self.state = Outside }
&Tokenizer { state: Outside } => { self.state = InATag(~"baz") }
}
}
}
fn main() {
let mut t1 = Tokenizer { state: InATag(~"foo") };
match t1 {
Tokenizer { state: InATag(*) } => { t1.state = Outside }
Tokenizer { state: Outside } => { /* impossible */ }
}
io::println(fmt!("Hello t1: %?", t1));
let mut t2 = Tokenizer { state: InATag(~"bar") };
t2.toggle();
io::println(fmt!("World t2: %?", t2));
}
I admit, I actually did not expect it to be as easy as the above, and I can easily believe that small changes to the above code could cause it to start failing to borrow-check. But without a more fleshed out example from the asker, it is hard to tell whether the above code would suit his purposes or not.
Oh, here's the output when I compile and run the code:
% rustc /tmp/m.rs
warning: no debug symbols in executable (-arch x86_64)
% /tmp/m
Hello t1: {state: Outside}
World t2: {state: Outside}
%

Resources