Something that would be very useful in Rust would be having associated types that can take lifetime parameters, which allows to implement things like the “streaming iterator” trait and in general support traits that can provide generic temporary values.
This could in theory be done right now by having an associated type with an HRTB lifetime bound for a trait with an associated type, like this:
trait R2T<'a>
{
type T;
}
trait StreamingIterator
{
type Item: for<'x> R2T<'x>;
fn next<'a>(&'a self) -> <Self::Item as R2T<'a>>::T;
}
Except that the compiler is broken so in many cases this kind of pattern doesn’t compile.
Any chance this could be fixed, since it’s quite an essential abstraction to have?
Also, having support for “for<'a: 'b>” syntax would be great as well, and then also “for<T>” (with bounds on T) and generic associated type constructors, and also specialization so the type mappings can be arbitrary.
This was a motivating use case for generic associated types. There is an ongoing effort to rework the internals of the trait system going on that should lay the groundwork for implementing this feature.
Agreed. This was a huge problem when designing rental, and I had to work around it with a gross syntactic hack instead of doing it the proper way with an associated type, because the compiler just wouldn’t accept that the type is always the same regardless of the trait’s lifetime param.
Even GAT won’t fix it completely, for cases where the HRTB lifetime isn’t on the trait itself but on the concrete type.
for<'a> <Foo<'a> as Deref>::Target
There’s no way to assure the compiler that the associated type is the same for all possible lifetimes. I’d be fine with types where that’s not the case being rejected, since all the types I’m concerned about satisfy this condition.
As for:
for<'a, 'b: 'a>
This would also be quite useful in rental. Lack of it currently prevents otherwise valid code from compiling, since the relationship of the HRTB closure lifetimes can’t currently be expressed, so the compiler considers them completely disjoint when they’re not.