-
Notifications
You must be signed in to change notification settings - Fork 55
possibility of merging this back to upstream? #44
Conversation
This is a huge change. - stream is supported For `impl Stream<Item = T, Error = E>`, yield type is `Result<T, StreamError<E>>` and return type is `()`. This signature reflects the fact that stream from futures v0.1 does not support terminating itself with error, and if it's supported in future, fn signature will be changed. StreamError is a internal error type which has `NotReady` variant. - non-static lifetime is supported This is implemented by prepending a special lifetime `'__returned_future` and bounding returned future like `impl Future + '__returned_future`. But this should **not** be done if signature matters (e.g. inside trait impl). Opt out is not implemented yet. - yield / return types are explicitly annotated So rustc can use them for type inference and error reporting. - await! macro works for different type of futures As user get `Result<T, E>` from `await!` regardless of future provided, `await!(if a { fut_a } else { fut_b })` expands to `if a { await!(fut_a) } else { await!(fut_b) }` and give `Result<T, E>` back to user.
I think this can be merged when futures v0.2 is realeased and it supports terminating stream with value. TODOs
Edit(2017/12/19): some more
|
Thanks for the PR! Sorry I'm having a little difficulty following the changes though. Before I dive into the code though I was hoping I could get a bit more of a high-level overview about the intended changes?
|
pmutil is a replacement for quote.
if false {
return {
let _v: io::Result<()> = unreachable!();
_v
});
} are used for error reporting, they should be correct.
I checked that rustfmt and syntax highlighter for rustdoc / vscode works.
I think this is correct. I'll take some time to think more about this.
yield ::futures::__rt::YieldType::not_ready(); , Even if And it also improves error reporting. For example, error[E0308]: mismatched types
--> $DIR/not-a-result.rs:8:13
|
8 | fn foo() -> u32 {
| ^^^ expected enum `std::result::Result`, found u32
|
= note: expected type `std::result::Result<_, _>`
found type `u32` It's because type annotation has UI test does not exists, but it improves error message for other user's mistake. error[E0308]: mismatched types
--> tests/stream-smoke.rs:33:18
|
33 | yield Ok(ch);
| ^^ expected char, found u8
error: aborting due to previous error
error: Could not compile `futures-await`. for #[async_stream]
fn chars(src: &str) -> impl Stream<Item = char, Error = ()> {
for ch in src.bytes() {
yield Ok(ch);
}
} instead of error[E0271]: type mismatch resolving `<impl futures::__rt::MyStream<u8, <[generator@tests/smoke.rs:122:32: 1:5 _] as futures::__rt::Generator>::Return> as futures::Stream>::Item == char`
--> tests/smoke.rs:122:16
|
122 | fn _chars() -> Result<(), i32> {
| ^^^^^^^^^^^^^^^ expected u8, found char
|
= note: required for the cast to the object type `futures::Stream<Error=i32, Item=char>`
error: aborting due to previous error
error: Could not compile `futures-await`.
for #[async_stream(boxed, item = char)]
fn _chars() -> Result<(), i32> {
for c in "abc".bytes(){
stream_yield!(c);
}
Ok(())
}
I think I should too. Current implementation works for free functions, but while writing a lexer with this I noticed that this sucks if it's used inside impl block because lifetime
Primarily I did it to test what can proc macro do, and to see accuracy of respanning. I just didn't revert it because user gives (I don't mind reverting it) I mean, // assuming error has timeout variant..
let req = if let Some(timeout) = timeout {
req.with_timeout(timeout).map_err(From::from)
} else {
req
};
await!(req); doesn't compile, because type of Alternatively, code below works. let req = if let Some(timeout) = timeout {
await!(req.with_timeout(timeout).map_err(From::from))
} else {
await!(req)
}; But I think code below makes meaning of let req = await!(if let Some(timeout) = timeout {
req.with_timeout(timeout).map_err(From::from)
} else {
req
}); Edit: formatting |
Lifetime issue seems like rust-lang/rust#45259 (or implicit self referential struct). #![feature(generators)]
fn main() {
move || {
yield true;
let mut i = "";
let r = &i;
yield panic!();
};
} fails to compile with error[E0626]: borrow may still be in use when generator yields
--> src/main.rs:8:22
|
8 | let r = &i;
| ^
9 | yield panic!();
| -------------- possible yield occurs here
Immovable generator will fix this lifetime issue. |
Fix regression from rustc 1.24.0-nightly (73bca2b9f 2017-11-28).
I discovered When the pr is merged, I'll remove pmutil and update this pr to use
Edit: added description |
Ok thanks for the explanation! (and sorry for the slow response) I think nowadays |
Opened #49 |
Closing as stream and lifetime issues are solved, and type inference is extracted to separated pull requests (#46 #49). Lifetime: #53 (comment) |
It's almost rewrite. I failed to split commits, but if you want, I'll extract part of these pr as a separate pr.
pmutil::smart_quote instead of quote::quote!
As this fork generates lots of code, I needed some ide support and span-aware quasi quotter.
But currently this crate works with git dependencies, so I should publish something like futures-await-pmutil.
Stream support
Syntax and return types differs from current upstream's.
await!
works for future and stream. This uses an associated constant::__rt::YieldType::NOT_READY
.Yield = Result<T, StreamError>
StreamError has a NotReady variant.
Return = ()
Current return type is ().
If stream v0.2 supports terminating with value, it'll be changed to reflect that.
Currently ? operator is not usable from this scope, as ? in rust means 'error is returned' instead of 'error is yielded as an item'.
Better type inference
Lifetime support
Fixes #11, #17.
expands to
But this isn't complete, and should implement opt-out.
Heterogeneous await
is equivalent to
await! macro lives in futures-async-macro
I did this before extracting pmutil as proc_macro can't export utils, and I'm not sure if this was a good idea.