-
-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
An alternate design for StreamingIterator
based on HRTBs
#25
Comments
StreamingIterator
based on HRTBsStreamingIterator
based on HRTBs
Yes, that's a possibility that you'll see discussed in some of the background for Generic Associated Types (GATs), like in the RFC here: It tends to infect HRTB lifetimes into in every place that wants to use it, especially when you build more APIs on top of it. |
That's true, although it's not like GATs avoid that in a significant way. You'll still see them everywhere: where
T: StreamingIterator,
for<'a> <T as StreamingIterator>::Item<'a>: Clone, versus the non-GAT version: where
T: for<'a> StreamingIterator<'a>,
for<'a> <T as StreamingIterator<'a>>::Item: Clone, Or this comparison: // with GATs
T: for<'a> StreamingIterator<Item<'a> = &'a u32>,
// no GATs
T: for<'a> StreamingIterator<'a, Item = &'a u32>, It's basically identical. It's also possible that this library could provide a trait alias for |
Ok, well this library isn't using GATs yet either. The limitation of using |
I was assuming you'd eventually want to switch to using GATs once they stabilize rather than keep the
That's true, although this helper could exist to avoid lifetimes in the pub trait RefStreamingIterator
where
Self: for<'a> StreamingIterator<'a, Item = &'a <Self as RefStreamingIterator>::RefItem>,
{
type RefItem: ?Sized;
}
impl<I: ?Sized, T: ?Sized> RefStreamingIterator for I
where
Self: for<'a> StreamingIterator<'a, Item = &'a T>,
{
type RefItem = T;
}
One of the reasons I wanted this design was to avoid having additional traits, because otherwise we'd end up having all of:
Which is really quite excessive, and only increases exponentially if we ever want to represent more properties. |
It's unclear. I'm helping maintain this crate, but I'm not the owner. There's also talk of adding a GAT |
Someone on zulip shared yet another design to emulate GAT: https://gist.github.com/jix/42d0e4a36ace4c618a59f0ba03be5bf5 |
Okay, so recently I've been working a lot with GAT-like traits and I've come to the conclusion that out of all the designs, the following one is definitely the best: pub trait StreamingIteratorLifetime<'a, ImplicitBounds: sealed::Sealed = sealed::Bounds<&'a Self>> {
type Item;
}
pub type Item<'a, I> = <I as StreamingIteratorLifetime<'a>>::Item;
pub trait StreamingIterator: for<'a> StreamingIteratorLifetime<'a> {
fn next(&mut self) -> Option<Item<'_, Self>>;
}
mod sealed {
pub trait Sealed {}
pub struct Bounds<T>(T);
impl<T> Sealed for Bounds<T> {}
} For the following reasons:
The primary disadvantage of this approach is the lack of Because of the issues with real GATs (that are unlikely to be fixed without a major addition in syntax that even hasn't been formally suggested at all), I do think that it would be best to actually push this idea forward, since it looks like even when real GATs land it will be the best option to achieve lifetime GATs. |
Now that https://docs.rs/lending-iterator exists I can close this issue. |
The design is this:
Here is a playground of it being used to implement
WindowsMut
. Note that it is working when neither the iterator nor the iterator's item are'static
.Note that I have only a vague idea of how this actually works, I'm not an expert on rustc. But the general idea is that the hidden type parameter on the trait effectively gives a
where Self: 's
bound to the trait, but in a special way that works with HRTBs.The text was updated successfully, but these errors were encountered: