Returning structure with generic arguments

I have a function that returns LazySortIteratorBy<T, F> but I’m not quite sure how to specify generic arguments for the return type in an example from https://docs.rs/crate/lazysort/0.2.1:

fn test(&self) -> ??? {
    let before: Vec<&str> = vec!["a", "cat", "sat", "on", "the", "mat"];
    before.iter().sorted_by(|a, b| {
        match a.len().cmp(&b.len()) {
            Equal => a.cmp(b),
            x => x
        }
    })
}

I’d like to understand:

  • how to return such type (in case of e.g. internal functions)
  • what is the best practice if this function was a public interface (e.g. wrap it in my own iterator to hide the implementation detail? define a type alias?)

you could just do

fn test(&self) -> impl Iterator<Item  = &str>
1 Like

Thank you @KrishnaSannasi that fits perfectly.

As a followup question, how does one go about specifying lifetimes when returning impl trait with borrowed values?

Let’s say the Vec is passed into the function like:

fn test(before: &Vec<&str>) -> impl Iterator<Item = &&str> {
    before.iter().sorted_by(|a, b| {
        match a.len().cmp(&b.len()) {
            Equal => a.cmp(b),
            x => x
        }
    })
}

The compiler says that

... impl Iterator<Item = &&str>
...                      ^ expected lifetime parameter

help: this function's return type contains a borrowed value, but the signature does not say which one of `before`'s 2 lifetimes it is borrowed from

Does this work?

fn test<'vec, 'item>(before: &'vec Vec<&'item str>) -> impl 'vec + Iterator<Item = &'vec &'item str>

Basically, the iterator has comes from the Vec<_> and so each reference that the iterator yields also comes from the Vec<_> (why they have lifetime 'vec), but the strings could come from somewhere else, so they have their own lifetimes ('item).

Thanks a lot, that did work. Your explanation helped me, I didn’t realise I needed to specify lifetimes for both && as &'vec &'item.

I don’t think you need to specify all of the lifetimes, I did because I wasn’t sure which ones were needed. You can remove some of the lifetime annotations to see which ones you actually need.