Using trait bounds on an associated type's type parameter

Hi, in other words how do I make the following work (it does not even compile)?

pub fn reversed2<U: DoubleEndedIterator>(iter: U) -> Vec<U::Item> {

Playpen link.

Note the following things do compile however...

pub fn reversed0<T: Clone>(xs: Vec<T>) -> Vec<T> {

pub fn reversed1<U: DoubleEndedIterator>(iter: U) -> Vec<U::Item> {
    iter.rev().collect::<Vec<U::Item>>() //Not using clone() here
1 Like

You need to let the compiler know that the item being iterated over is cloneable, so:

pub fn reversed1<'a, U, T>(iter: U) -> Vec<T> 
    where U: DoubleEndedIterator<Item=&'a T>, T : 'a + Clone
1 Like

Thanks Pixel! The where U: DoubleEndedIterator<Item=&'a T> syntax is new to me. Do you know of any good articles/tutorials which explain advanced usage of generics, traits, lifetimes etc.?

Unfortunately no, I don't know of any articles/tutorials, I only found that by looking at the definitions for the Iterator::cloned() method here.

The generics section of the book explains generics/type parameters.

The traits section explains trait bounds, including the where syntax.

The traits and associated types sections in the book currently have no example or explanation of bounds on associated types, i.e. where T: MyTrait <AssociatedType=Foo>, which is a harmful omission in my opinion.

The very last example in the associated types section (let obj = Box::new(graph) as Box<Graph<N=Node, E=Edge>>;) does show the MyTrait<AssociatedType=Foo> syntax. And it is shown in the Traits section that a trait with a type parameter can go on a trait bound (see the normal and inverse examples), so it is very natural to assume that the = syntax will also work in that context.

No example of that specific construction seems to be given. But I'm not sure if it would be worth the additional verbosity to talk about that particular case in the book.

1 Like

Thanks kainino!