I'm attempting to define a trait whose method returns an Iterator of &str. A basic skeleton would be:
pub trait Stringy {
fn strings(&self) -> ???
}
where ??? should be some type that reflects the constraint correctly, namely Iterator<Item = &str>.
We can't impl Iterator<Item = &str> here because the "impl Trait" pattern isn't allowed here. Nor is setting this to a generic I: Iterator correct, because then the caller can define what the Iterator is. Since I don't want to have any type (or lifetime) params on Stringy itself, it seems like an associated type is what's necessary here.
The "straightforward" way, involving unstable features, would be to use a GAT ("generic associated type").
#![feature(generic_associated_types)]
pub trait Stringy {
type Iter<'a>: Iterator<Item = &'a str>
where
Self: 'a;
fn strings(&self) -> Self::Iter<'_>;
}
It's possible to work around the fact that GATs with lifetime arguments though. Following a recipe of mine (that @quinedot apparently likes to link to a lot, so let me do the same myself), you could translate this thing into something like
depending on your use-case. You might still need the trick with the _Outlives parameter if you still want to use HRTBs (like T: for<'a> Stringy<'a>) for types that are non-T: 'static. (TL;DR, it's not unlikely you wont need the trick with the _Outlives parameter.) It's not possible to tell which solution is "the best" since you haven't provided any example types that implement the trait and example use-cases.