-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Allow unsized closures in iterator adaptors #43717
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
Conversation
For example, `Map<I, F>` can be generalized to `Map<I, F: ?Sized>`, which allows for example the type `Map<I, FnMut(Foo) -> Bar>` as an iterator. Generalize `filter, filter_map, flat_map, inspect, map, skip_while, take_while` like this. A struct can only have one unsizeable field, so we have to pick either unsizing the iterator or closure parameter for all of these, but it seems right to pick the closure parameter. The whole struct itself can already coerce to the `Iterator` type.
(rust_highfive has picked a reviewer for you, use r? to override) |
Thanks for the PR @bluss! This looks pretty nifty to me! You mentioned though that you don't have any particular motivational goal with this change, and that'd be my next question! This makes sense to me but I'm not really sure how we'd take advantage of it? Do you have some example use cases in mind though? |
I wanted this in something like:
where it was fine for MyAdaptor to be ?Sized. I do not remember anymore the exact use case I had for this though, but I do remember being annoyed by this limitation enough to consider filling an issue. |
where G: FnMut(Acc, Self::Item) -> Acc, | ||
Self: Sized, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
couldn't you also just add an F: Sized
bound?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not allowed unfortunately. Doesn't match the trait.
Hm I'm still sort of stuck about what to do for this. This is providing a guarantee in the standard library that we can't ever change. Despite that, though, there's no concrete use cases proposed yet? |
I agree with that as a rule of maintainership; no point in merging if it doesn't have its use case clearly described. The only thing I saw here was the factor of extending the api to the conventions of Rust and internal logic of its type system, and the expectation that we provide as generic items as we practically can. I can't actually come up with a use case (I'm looking forward to Regarding @nagisa's example, Rust doesn't in practice allow such a thing verbaitm, since one can't fill the struct field.. it would have to be a type parameter and undergo the unsizing coercion, right? // Can be cast to `MyAdaptor<Fn(u8) -> u32>`.
struct MyAdaptor<F: ?Sized> {
...,
inner: ::std::iter::Map<::std::ops::Range<u8>, F>,
} |
ping @alexcrichton, wdyt about the last comment here? |
Ah oops sorry. Ok it sounds like this is mostly opportunistic for now and doesn't have a motivating use case, so I'm going to close this. If a use case comes up though please feel free to resubmit! |
For example,
Map<I, F>
can be generalized toMap<I, F: ?Sized>
,which allows for example the type
Map<I, FnMut(Foo) -> Bar>
as aniterator.
Generalize
filter, filter_map, flat_map, inspect, map, skip_while, take_while
like this.
A struct can only have one unsizeable field, so we have to pick either
unsizing the iterator or closure parameter for all of these, but it
seems right to pick the closure parameter. The whole struct itself can
already coerce to the
Iterator
type.Fixes #38133
Extra Remarks
Map::fold
here wasmistaken (and trying that finds a type inference bug). Instead the remaining
blemish is that we have to use
&mut self.f
inMap::fold
. The compilerdoesn't understand that
Self: Sized
impliesF: Sized
there.about this and it is technically correct.