How to create a recursive queue? - rust

I am trying to implement a recursive queue using the trait Element<T> as a container for all the functions of the different nodes of the queue and two structs implementing it called Node<T> and End.
The Node<T> struct is supposed to handle all the functionality within the queue itself and the End struct's purpose is to deal with the case of the last node.
I've got the following code:
trait Element<T> {
fn append_item(self, item: T) -> Node<T>;
}
struct Node<T> {
data: T,
successor: Box<dyn Element<T>>
}
impl<T> Element<T> for Node<T> {
fn append_item(mut self, item: T) -> Node<T> {
self.successor = Box::new(self.successor.append_item(item));
self
}
}
struct End;
impl<T> Element<T> for End {
fn append_item(self, item: T) -> Node<T> {
Node { data: item, successor: Box::new(self) }
}
}
The problem is, that I get two errors:
Cannot move a value of type dyn Element<T>
The parameter type T may not live long enough
both on the same line in Node::append_item.
Now, I get why the first error occurs (because the size of dyn Element<T> cannot be statically determined) but I don't know how to work around it and I have no idea why the second error occurs.

error[E0161]: cannot move a value of type `dyn Element<T>`
--> src/lib.rs:12:35
|
12 | self.successor = Box::new(self.successor.append_item(item));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the size of `dyn Element<T>` cannot be statically determined
The issue here is that fn append_item(self, item: T) takes self by value, but in this case self has type dyn Element<T>, which is unsized and can therefore never be passed by value.
The easiest solution here is to just take self: Box<Self> instead. This means that this method is defined on a Box<E> instead of directlThis will work perfectly fine with trait objects like dyn Element<T>, and it does not require the type to be sized.
(Additionally, in the updated code below, I've changed the return type to Box<Node<T>> for convenience, but this is not required per se, just a bit more convenient.)
trait Element<T> {
fn append_item(self: Box<Self>, item: T) -> Box<Node<T>>;
}
impl<T> Element<T> for Node<T> {
fn append_item(mut self: Box<Self>, item: T) -> Box<Node<T>> {
self.successor = self.successor.append_item(item);
self
}
}
impl<T> Element<T> for End {
fn append_item(self: Box<Self>, item: T) -> Box<Node<T>> {
Box::new(Node { data: item, successor: self })
}
}
[Playground link]
error[E0310]: the parameter type `T` may not live long enough
--> src/lib.rs:12:26
|
12 | self.successor = Box::new(self.successor.append_item(item));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
The issue here is that dyn Trait has an implicit lifetime. In reality, it's dyn '_ + Trait. What exactly that lifetime is depends on the context, and you can read the exact rules in the Rust reference, but if neither the containing type nor the trait itself has any references, then the lifetime will always be 'static.
This is the case with Box<dyn Element<T>>, which really is Box<dyn 'static + Element<T>>. In other words, whatever type is contained by the Box must have a 'static lifetime. For this to be the case for Node<T>, it must also be that T has a 'static lifetime.
This is easy to fix, though: just follow the compiler's suggestion to add a T: 'static bound:
impl<T: 'static> Element<T> for Node<T> {
// ^^^^^^^^^
// ...
}
[Playground link)

Frxstrem already elaborated how to get around the need to move by using Box<Self> as receiver. If you need more flexibility in the parameter type (i.e. be able to hold on to references as well as owned types) instead of requiring T: 'static you can introduce a named lifetime:
trait Element<'a, T: 'a> {
fn append_item(self: Box<Self>, item: T) -> Node<'a, T>;
}
struct Node<'a, T: 'a> {
data: T,
successor: Box<dyn Element<'a, T> + 'a>,
}
impl<'a, T: 'a> Element<'a, T> for Node<'a, T> {
fn append_item(self: Box<Self>, new_data: T) -> Node<'a, T> {
Node {
successor: Box::new(self.successor.append_item(new_data)),
..*self
}
}
}
struct End;
impl<'a, T: 'a> Element<'a, T> for End {
fn append_item(self: Box<Self>, data: T) -> Node<'a, T> {
Node {
data,
successor: self,
}
}
}

Related

Lifetime and associated types

I have this enum:
enum Node<T> {
Leaf(T),
Children(Vec<Node<T>>),
}
And want to implement the Iterator trait for Node.
I created this struct and tried to implement the IntoIterator trait:
struct NodeIter<'a, T>{
children: &'a [Node<T>],
parent: Option<&'a Node<T>>,
}
impl<'a, T> IntoIterator for Node<T> {
type Item = T;
type IntoIter = NodeIter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
todo!()
}
}
I can not figure out the correct lifetime specifiers, I end up getting this error:
error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
--> src/tree_my.rs:44:6
|
44 | impl<'a, T> IntoIterator for Node<T> {
| ^^ unconstrained lifetime parameter
I am new to Rust and I am not sure if I am doing it wrong or if it is not possible. Because I have read about similar problems. The problem seems to have something to do with traits (IntoIterator in my case) and associated types. I also read something about GAT.
Maybe someone could explains this problem and how one would solve it.
Rust Playground
IntoIterator::into_iter consumes its argument. This means that once you've called node.into_iter() the node no longer exists, but it looks like you want your NodeIter to keep references to node which is impossible since it's no longer around.
You will need to either change NodeIter to take ownership of the original Node so that NodeIter can keep the Node alive for as long as it needs it, or implement IntoIter for references to Node (which will consume the reference, but keep the original Node intact):
enum Node<T> {
Leaf(T),
Children(Vec<Node<T>>),
}
struct NodeIter<'a, T>{
children: &'a [Node<T>],
parent: Option<&'a Node<T>>,
}
impl<'a, T> Iterator for NodeIter<'a, T> {
type Item = T;
fn next (&mut self) -> Option<Self::Item> {
todo!();
}
}
impl<'a, T> IntoIterator for &'a Node<T> {
type Item = T;
type IntoIter = NodeIter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
todo!()
}
}
Playground

Rust - implementing trait for Deref: the parameter type `T` may not live long enough

I have a trait:
trait Foo {
fn bar(&self) -> Cow<str>;
}
And I want to implement it for any type that implements Deref with a target of a type that implements Foo. Basically:
impl<T: Foo, D: std::ops::Deref<Target = T>> Foo for D {
fn bar(&self) -> Cow<str> {
<T as Foo>::bar(std::ops::Deref::deref(self))
}
}
Unfortunately, this gives the error the parameter type T may not live long enough.
My understanding is that T could have a reference within it that has a short lifetime, and the lifetime bound of the return value of Cow<str> is linked to the lifetime of &self due to lifetime elision, which would cause problems.
I'm not sure how I can fix this, since I'm not able to bound any of the lifetimes in bar. I can try to make sure T lives as long as &self, but this doesn't work.
impl<'a, T: Foo + 'a, D: std::ops::Deref<Target = T>> Foo for D {
fn bar(&'a self) -> Cow<'a, str> {
<T as Foo>::bar(std::ops::Deref::deref(self))
}
}
I get the error method not compatible with trait since the lifetimes don't match the trait defenition anymore. I've tried all sorts of different ways of adding lifetime bounds and I always get one of those two errors.
I am able to implement Foo for a specific type that implements Deref:
impl<T: Foo> Foo for Box<T> {
fn bar(&self) -> Cow<str> {
<T as Foo>::bar(self)
}
}
I'm not sure why that works but the original example doesn't.
The Box version works because of the deref coercion the compiler will do when it sees a reference and expects a different reference.
You can use the same mechanic when using a generic implementor of Deref to ensure that it Derefs to an owned type you can simply add a 'static lifetime bound on T like this:
impl<T: Foo + 'static, D: std::ops::Deref<Target = T>> Foo for D {
fn bar(&self) -> Cow<str> {
<T as Foo>::bar(self)
}
}
playground
Note: there is rarely a need to call methods of std::ops traits directly, they're all just the methods behind Rusts operators, deref for example is the method behind unary *
Update:
Since there is an additional requirement that T might not be static we have to thread through the lifetime like you tried in your second example, like the error you're getting suggest you have to adjust the trait to take a lifetime as well:
use std::borrow::Cow;
trait Foo<'a> {
fn bar(&self) -> Cow<'a, str>;
}
impl<'a, T: Foo<'a>, D: std::ops::Deref<Target = T>> Foo<'a> for D {
fn bar(&self) -> Cow<'a, str> {
<T as Foo>::bar(self)
}
}
struct S<'a> {
val: &'a str,
}
impl<'a> Foo<'a> for S<'a> {
fn bar(&self) -> Cow<'a, str> {
todo!()
}
}
fn main() {
let val = String::from("test");
let s = S { val: &val }; // error: `val` does not live long enough
let b = Box::new(s);
let cow = Foo::bar(&b); // argument requires that `val` is borrowed for `'static`
}

Issues constraining implementation lifetimes on type without lifetime parameter

I'm trying to implement a BST in Rust (for HW3 in this lovely intro to Rust), and I'm running into errors with lifetimes, and how to constrain lifetimes for types that are related to types without a lifetime.
#[derive(Debug)]
pub struct BST<T>
where T: Ord
{
root: Option<Box<Node<T>>>,
}
// A couple dozen lines of BST stuff
impl<'a, T> IntoIterator for BST<T>
where T: Ord
{
type Item = T;
type IntoIter = BSTIter<'a, T>; // <- my intuition is that I should
// be able to say "BSTIter lives as
// long as BST."
fn into_iter(&'a mut self) -> BSTIter<'a, T> {
BSTIter::new(&mut self)
}
}
pub struct BSTIter<'a, T: 'a>
where T: Ord + 'a
{
bst: &'a mut BST<T>,
node_list: Vec<&'a Node<T>>, // this is where the need for a lifetime on
// BSTIter comes from
}
impl<'a, T> BSTIter<'a, T>
where T: Ord
{
fn new(&mut bst: BST<T>) -> BSTIter<'a, T> {
let traverse_stack = Vec::new();
if let Some(ref x) = bst.root {
traverse_stack.push(x);
}
BSTIter {
bst: bst,
node_list: traverse_stack,
}
}
}
impl<'a, T> Iterator for BSTIter<'a, T>
where T: Ord
{
type Item = T;
fn next(&mut self) -> Option<T> {
// BST iteration details
}
}
As it stands, this code spits out the error
error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
--> src/lib.rs:117:7
|
117 | impl<'a, T> IntoIterator for BST <T> where T: Ord {
| ^^ unconstrained lifetime parameter
If the IntoIterator trait didn't require me to specify type IntoIterator = BSTIter, the implementation block could just have an into_iter method signature of into_iter<'a>(&'a mut self) -> BSTIter<'a, T>. Since I need to specify the lifetime for BSTIter, it seems like I need to specify a lifetime for the entire BST type. Again, my instinct says that I shouldn't have to specify a lifetime on BST to be able to create an iterator for it.
I realize the two solutions to this are likely one (or both) of
There's a language feature that helps me get around this
Somewhere along the way, my code became very much not idiomatic Rust
If I could get help on either how to make the above code snippet work, or how I should be approaching these lifetime and ownership details in general, it would be very much appreciated!
You've misunderstood the purpose and usage of IntoIterator. It converts a value into an iterator; consuming the value in the process. However, your iterator is attempting to return references to the collection. You cannot return references into the iterator, so it makes no sense to consume the tree, transferring ownership to the iterator.
The fact that you've called it BSTIter instead of BSTIntoIter shows promise; as that's the idiomatic name for an iterator that returns references.
You want to implement IntoIterator for &'a BST<T>, not BST<T>. You could also implement it for BST<T>, but then you'd want to yield T, not &T.
After fixing that, there's lots of compiler errors: mismatched types all throughout the code, incorrect method signatures in traits (fn into_iter(self) is all you are allowed), for some reason there's a mutable reference to the tree, variables aren't mutable when they should be....
#[derive(Debug)]
struct Node<T>(Option<Box<T>>);
#[derive(Debug)]
pub struct BST<T>
where T: Ord
{
root: Option<Box<Node<T>>>,
}
impl<'a, T> IntoIterator for &'a BST<T>
where T: Ord
{
type Item = T;
type IntoIter = BSTIter<'a, T>;
fn into_iter(self) -> BSTIter<'a, T> {
BSTIter::new(self)
}
}
pub struct BSTIter<'a, T: 'a>
where T: Ord + 'a
{
bst: &'a BST<T>,
node_list: Vec<&'a Node<T>>,
}
impl<'a, T> BSTIter<'a, T>
where T: Ord
{
fn new(bst: &'a BST<T>) -> BSTIter<'a, T> {
let mut traverse_stack = Vec::new();
if let Some(ref x) = bst.root {
traverse_stack.push(&**x);
}
BSTIter {
bst: bst,
node_list: traverse_stack,
}
}
}
impl<'a, T> Iterator for BSTIter<'a, T>
where T: Ord
{
type Item = T;
fn next(&mut self) -> Option<T> {
None
}
}
fn main() {}

How do you write a trait that returns an iterator?

Broadly speaking my goal is this:
For some known type Bar...
Have a trait Foo with a function: get_iterator<T>() -> T where T: Iterator<Item = Bar>
The instance of the iterator borrows the original object Foo is implemented on.
I imagine it working like this:
let mut foo = Foo;
let bar = foo.get_iterator();
foo.mutable_call(); // <-- This fails, because foo is borrowed in bar
for x in bar {
...
}
So, that's the goal, and here's my attempt, which I can't seem to get working:
struct ValsFromT<'a, T: 'a> {
parent:&'a T,
offset: usize,
}
struct Val;
trait HasValsIterator<T> {
fn val_iterator(&self) -> T where T: Iterator<Item = Val>;
}
struct Foo;
impl<'a> Iterator for ValsFromT<'a, Foo> {
type Item = Val;
fn next(&mut self) -> Option<Val> {
return None;
}
}
impl<'a> HasValsIterator<ValsFromT<'a, Foo>> for Foo {
fn val_iterator(&'a self) -> ValsFromT<'a, Foo> {
return ValsFromT {
offset: 0usize,
parent: self
};
}
}
fn takes_vals<T>(instance:T) where T: HasValsIterator<T> {
// ...
}
#[test]
fn test_foo() {
let x = Foo;
takes_vals(x);
}
(playpen: http://is.gd/wys3fx)
We're getting the dreaded concrete/bound lifetime error here, because of trying to return an iterator instance that references self from the trait function:
<anon>:22:3: 27:4 error: method `val_iterator` has an incompatible type for trait:
expected bound lifetime parameter ,
found concrete lifetime [E0053]
<anon>:22 fn val_iterator(&'a self) -> ValsFromT<'a, Foo> {
<anon>:23 return ValsFromT {
<anon>:24 offset: 0usize,
<anon>:25 parent: self
<anon>:26 };
<anon>:27 }
<anon>:22:3: 27:4 help: see the detailed explanation for E0053
Is there some way of doing this?
Unfortunately, Veedrac's suggestion doesn't work directly. You will get the following error if you'd try to use val_iterator() method on instance inside takes_vals():
<anon>:31:25: 31:39 error: the trait `core::iter::Iterator` is not implemented for the type `U` [E0277]
<anon>:31 let iter = instance.val_iterator();
^~~~~~~~~~~~~~
<anon>:31:25: 31:39 help: see the detailed explanation for E0277
<anon>:31:25: 31:39 note: `U` is not an iterator; maybe try calling `.iter()` or a similar method
error: aborting due to previous error
playpen: application terminated with error code 101
This (and some other further errors) requires changing the signature of the function to this one:
fn takes_vals<'a, T: 'a, U: Iterator<Item=Val>+'a>(instance: T) where T: HasValsIterator<'a, U>
However, even this doesn't work yet:
<anon>:31:16: 31:24 error: `instance` does not live long enough
<anon>:31 let iter = instance.val_iterator();
^~~~~~~~
<anon>:30:97: 32:2 note: reference must be valid for the lifetime 'a as defined on the block at 30:96...
<anon>:30 fn takes_vals<'a, T: 'a, U: Iterator<Item=Val>+'a>(instance: T) where T: HasValsIterator<'a, U> {
<anon>:31 let iter = instance.val_iterator();
<anon>:32 }
<anon>:30:97: 32:2 note: ...but borrowed value is only valid for the scope of parameters for function at 30:96
<anon>:30 fn takes_vals<'a, T: 'a, U: Iterator<Item=Val>+'a>(instance: T) where T: HasValsIterator<'a, U> {
<anon>:31 let iter = instance.val_iterator();
<anon>:32 }
Remember that the trait requires that val_iterator() accepts the target by reference with lifetime 'a. This lifetime in this function is an input parameter. However, when val_iterator() is called on instance, the only lifetime which can be specified for the reference is the one of instance which is strictly smaller than any possible 'a as a parameter, because it is a local variable. Therefore, it is not possible to pass instance by value; you can only pass it by reference for lifetimes to match:
fn takes_vals<'a, T: 'a, U: Iterator<Item=Val>+'a>(instance: &'a T) where T: HasValsIterator<'a, U> {
let iter = instance.val_iterator();
}
This works.
I'd like to add that using associated types instead of type parameters would be more correct semantically:
trait HasValsIterator<'a> {
type Iter: Iterator<Item=Val> + 'a;
fn val_iterator(&'a self) -> Self::Iter;
}
impl<'a> HasValsIterator<'a> for Foo {
type Iter = ValsFromT<'a, Foo>;
fn val_iterator(&'a self) -> ValsFromT<'a, Foo> { ... }
}
fn takes_vals<'a, T: 'a>(instance: &'a T) where T: HasValsIterator<'a> {
...
}
I say that this is more correct because the type of the iterator is determined by the implementor, that is, it is "output" type, which are modeled by associated types. As you can see, takes_vals() signature also shrank considerably.
Ideally, HasValsIterator trait should have been defined like this:
trait HasValsIterator {
type Iter<'a>: Iterator<Item=Val> + 'a
fn val_iterator<'a>(&'a self) -> Iter<'a>;
}
This way, val_iterator() would in any situation, including when HasValsIterator implementor is passed by value. However, Rust is not there yet.

Trait to store structs with different generic parameters

I need to store in the same Vec instances of the same struct, but with different generic parameters. This is the struct definition:
struct Struct<'a, T: 'a> {
items: Vec<&'a T>
}
The struct has a method returning an iterator to a type that does not depend on the generic type parameter T:
impl<'a, T: 'a> Struct<'a, T> {
fn iter(&self) -> slice::Iter<&i32> {
unimplemented!()
}
}
I need to access this method for those different structs in the vector, so I've implemented this trait:
type Iter<'a> = Iterator<Item=&'a i32>;
trait Trait {
fn iter(&self) -> Box<Iter>;
}
And I've implemented the trait for Struct:
impl<'a, T: 'a> Trait for Struct<'a, T> {
fn iter(&self) -> Box<Iter> {
Box::new(self.iter())
}
}
But the compiler complains:
<anon>:21:9: 21:30 error: type mismatch resolving `<core::slice::Iter<'_, &i32> as core::iter::Iterator>::Item == &i32`:
expected &-ptr,
found i32 [E0271]
<anon>:21 Box::new(self.iter())
^~~~~~~~~~~~~~~~~~~~~
<anon>:21:9: 21:30 help: see the detailed explanation for E0271
<anon>:21:9: 21:30 note: required for the cast to the object type `core::iter::Iterator<Item=&i32> + 'static`
<anon>:21 Box::new(self.iter())
^~~~~~~~~~~~~~~~~~~~~
I've tried different possibilities for lifetime parameters in the trait, but none of them work. How can I make this work?
Rust Playground snippet
Edit
As pointed out by #MatthieuM. one problem is that the type alias is not working properly. Here's another example demonstrating this:
use std::slice;
type Iter<'a> = Iterator<Item=&'a i32>;
struct Struct<'a> { _phantom: std::marker::PhantomData<&'a i32> }
impl<'a> Struct<'a> {
fn direct<'b>(i: &'b slice::Iter<'a, i32>) -> &'b Iterator<Item=&'a i32>
{ i }
fn aliased<'b>(i: &'b slice::Iter<'a, i32>) -> &'b Iter<'a>
{ i }
}
In this example, direct compiles, but aliased not, with the error:
<anon>:12:7: 12:8 error: the type `core::slice::Iter<'a, i32>` does not fulfill the required lifetime
<anon>:12 { i }
^
note: type must outlive the static lifetime
But they seem to be the same thing. What's happening?
Problem 1 — slice::Iter<T> has an Iterator::Item of &T, thus your reference levels are mismatched. Change your method to be
fn iter(&self) -> slice::Iter<i32>
Problem 2 — Box<SomeTrait> is equivalent to Box<SomeTrait + 'static>, but your iterator does not live for the 'static lifetime. You need to explicitly bring in a lifetime:
Box<SomeTrait + 'a>
Problem 3 — I don't understand how you can create a type alias for a trait, that seems very odd. You probably don't want it anyway. Instead, create a type alias for the whole boxed version:
type IterBox<'a> = Box<Iterator<Item=&'a i32> + 'a>;
Problem 4 — Rearrange your main so that references will live long enough and add mutability:
fn main() {
let i = 3;
let v = vec![&i];
let mut traits : Vec<Box<Trait>> = Vec::new();
traits.push(Box::new(Struct{ items: v }));
}
All together:
use std::slice;
type IterBox<'a> = Box<Iterator<Item=&'a i32> + 'a>;
trait Trait {
fn iter<'a>(&'a self) -> IterBox;
}
struct Struct<'a, T: 'a> {
items: Vec<&'a T>
}
impl<'a, T: 'a> Struct<'a, T> {
fn iter(&self) -> slice::Iter<i32> {
unimplemented!()
}
}
impl<'a, T: 'a> Trait for Struct<'a, T> {
fn iter(&self) -> IterBox {
Box::new(self.iter())
}
}
fn main() {
let i = 3;
let v = vec![&i];
let mut traits: Vec<Box<Trait>> = Vec::new();
traits.push(Box::new(Struct { items: v }));
}

Resources