-
Notifications
You must be signed in to change notification settings - Fork 341
FromStream impl for Option<T> + Revised impl for Vec<T> #265
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
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3321071
to
fb7582b
Compare
3 tasks
yoshuawuyts
approved these changes
Oct 1, 2019
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.
This is great; thanks so much!
bors bot
added a commit
that referenced
this pull request
Oct 4, 2019
266: Changes Extend trait in order to allow streams that yield references r=yoshuawuyts a=sunjay This is not ready to merge yet. I am mainly opening it so we can discuss a change I had to make to the `Extend` trait. cc @yoshuawuyts @stjepang (and anyone else interested) ## Before this can be merged - [x] Discuss/Approve changes to `Extend` trait - [x] Change to using `for_each` after #264 is merged - [ ] (optional) Wait until a `copied()` method is added to `StreamExt` so that the `&char` impl can be finished. - We can also just comment out or remove the impl that uses `copied` until that is added ## Changes To The Extend Trait While writing the impls of the `Extend` trait for the `String` type, I noticed that certain impls weren't possible because there is no bound on `Extend` that guarantees that the type `A` being yielded from the stream actually lives long enough. We probably didn't run into this earlier because this usually isn't a problem for owned values since the compiler doesn't have to worry about whether they will out live the stream that they come from. I ran into this because of the `Extend` impls that consume streams of references. The difference between the async `Extend` and the standard library `Extend` is that the async `Extend` returns a value that still references the input stream. That means that if `A` is any reference type, the compiler needs to be able to guarantee that `A` will be around as long as the `Future` returned from the trait method is around. To fix this, I had to add the bound shown below: ```patch pub trait Extend<A> { /// Extends a collection with the contents of a stream. fn stream_extend<'a, T: IntoStream<Item = A> + 'a>( &'a mut self, stream: T, - ) -> Pin<Box<dyn Future<Output = ()> + 'a>>; + ) -> Pin<Box<dyn Future<Output = ()> + 'a>> where A: 'a; } ``` This guarantees that each value of type `A` will last at least as long as our boxed future does. The bound had to be in a where clause on the method (and not on the declaration of `A` because the lifetime `'a` isn't in scope at the trait level. I don't think there are any negative consequences of using a where clause like this, but that's why I wanted to bring it up for discussion. In addition to this, I had to ensure that when writing the `Extend` impls for `String` I appropriately bounded the lifetime of the references from the stream. You can see this in the code below with `where 'b: 'a`. ```rust impl<'b> Extend<&'b str> for String { fn stream_extend<'a, S: IntoStream<Item = &'b str> + 'a>( &'a mut self, stream: S, ) -> Pin<Box<dyn Future<Output = ()> + 'a>> where 'b: 'a { //TODO: This can just be: stream.into_stream().for_each(move |s| self.push_str(s)) Box::pin(stream.into_stream().fold((), move |(), s| self.push_str(s))) } } ``` I should note that initially I tried to make it work with just the impl shown above, without modifying the `Extend` trait. This doesn't work because it would be a stricter bound than what is found in the trait itself. Rust does not allow stricter bounds like that because it could potentially cause unsoundness when dealing with generics. Of course, I am totally open to being completely wrong in my understanding of how to resolve this issue. I tried to solve the problem with as minimal of a change as possible. Please let me know if you have some better ideas or other suggestions. ## `FromStream` impls for String The purpose of adding these `Extend` impls is to continue my work from #129 in adding the rest of the `FromStream` impls. The `Extend` impls are used directly to add all of the `FromStream` impls for `String`. Just like with #207 and #265, this adds a new `string` module that is unstable just like the other modules added for `FromStream`. Co-authored-by: Sunjay Varma <[email protected]>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
cc #129
The
FromStream
impl forOption<T>
is almost identical to the one forResult<T>
(and thus also almost identical to the one in the standard library). Just like with #207, this adds a new module for option and leaves it unstable with the otherFromStream
impls.I've also re-implemented
FromStream
forVec<T>
in terms of the asyncExtend
trait. This better matches the standard library and also gives us some code re-use as the previous impl was essentially the same as the implementation ofExtend
.I'm waiting on a few more methods to be added to stream before I can add the rest of the
FromStream
impls. @montekki has started to work on that in #264. Thanks!