I recently started playing with GATs, but I ran into a lifetime issue which, after couple of evenings, I don't seem to be able to fix myself. I'll probably start with a minimized example:
error[E0309]: the parameter type `Ifc` may not live long enough
--> src/main.rs:26:5
|
25 | impl<Ifc> ReadData for ColorDisplay<Ifc> {
| --- help: consider adding an explicit lifetime bound...: `Ifc: 'a`
26 | type Iter<'a> = ColorDisplayDataIter<'a, Ifc>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `Ifc` will meet its required lifetime bounds
I basically understand where the error is coming from, but it seems to be impossible to constrain Ifc by the lifetime 'a.
I don't want to add the Ifc type parameter to the ReadData trait as Ifc is an implementation detail of any Display that will implement the ReadData trait.
Is this caused by the current state of GAT implementation or will this still be impossible once GATs land in stable.
Or I might be completely misunderstanding something
Note that generic associated types that are only generic over lifetime parameters (so not over type parameters) can be encoded using ordinary traits in stable rust:
// Only used with MutRef == &'a mut Self
// The &'a mut Self parameter gives rise to an implicit Self: 'a bound,
// which is important for the HRTB below to work.
trait HasReadDataIter<MutRef> {
type Iter: Iterator<Item = u16>;
}
// Higher-ranked trait bound (HRTB) as supertrait. Implicit bound from the &'a mut Self
// means this only ranges over 'a with Self: 'a
trait ReadData: for<'a> HasReadDataIter<&'a mut Self> {
fn read<'a>(&'a mut self) -> <Self as HasReadDataIter<&'a mut Self>>::Iter;
}
impl<'a, Ifc> HasReadDataIter<&'a mut Self> for ColorDisplay<Ifc> {
type Iter = ColorDisplayDataIter<'a, Ifc>;
}
impl<Ifc> ReadData for ColorDisplay<Ifc> {
fn read<'a>(&'a mut self) -> <Self as HasReadDataIter<&'a mut Self>>::Iter {
ColorDisplayDataIter { ifc: &mut self.ifc }
}
}
It's cool that that snippet works, and if I needed to build something with that I'd be glad I could do it in stable today. But let's be honest: that really obscures intent.
I had a hunch this could be solved with just lifetime HRTB, but so far I only used them like twice.
Now that I look at your example, it makes perfect sense, but I wouldn't come up with this myself with my current (obviously very limited ) understanding of HRTBs.
I'll probably use it, but I must agree with @jjpe that the GAT version seems to better describe the intent, so probably switch to it once GATs hit stable.
Thanks again, you saved me another evening headache.