-
Notifications
You must be signed in to change notification settings - Fork 55
Handle borrowed arguments #11
Comments
The better alternative is probably to use Edit: That is, this doesn't compile: #[async] fn foo(x: &Bar) -> Result<&Baz, ()> {
Ok(await!(...))
} but this does: fn foo<'a>(x: &'a Bar) -> impl Future<Item = &'a Baz, Error = ()> + 'a {
async_block! {
Ok(await!(...))
}
} |
Maybe this should be included in the README. @alexcrichton Any issues with this approach? |
Thanks for opening a tracking issue @alex! I think we can probably support the case brought up by @Arnavion by tweaking the procedural macro (taking into account lifetime arguments or otherwise not mentioning One worry I'd have though is that cases like @Arnavion brought up are quite rare, and otherwise requiring |
FWIW, I found the technique @Arnavion suggested pretty effective at resolving some lifetime issues that I was otherwise having trouble with. |
Yeah, that's possible. The project I'm trying |
BTW another advantage of fn post<'a>(client: &'a Client, body: &Body) -> impl Future<...> + 'a {
let builder = client.inner_http_client.post(body);
async_block! {
let response = await!(builder.send())?;
let result = response.deserialize()?;
Ok(result)
}
}
I don't know if there's any way to make |
Indeed! I'd love to play around with ideas about how to make this sort of pattern more ergonomic, although I haven't quite figured out how to do so yet :( |
|
Would be good to point folks to this workaround. It wasn't discoverable, but immediately solved my problem. I understand it may not be the best long term solution but it certainly helps for now. |
I really like the approach by @Arnavion but I am running into a problem when working with #![feature(conservative_impl_trait, generators, proc_macro)]
extern crate futures_await;
use futures_await as futures;
use futures::prelude::*;
use futures::Future;
struct Foo { i: u8 }
impl Foo {
fn increase<'a>(&'a mut self) -> impl Future<Item=u8, Error=()> + 'a {
async_block! {
self.i += 1;
Ok(self.i)
}
}
}
fn run<'a>(foo: &'a mut Foo) -> impl Future<Item=u8, Error=()> + 'a {
async_block! {
// await!(foo.increase())?; // compiler fails if this line is included!
await!(foo.increase())
}
}
fn main() {
let mut foo = Foo { i: 0 };
run(&mut foo).wait().unwrap();
} This code works fine if I just do only one call to
I do not see why the first borrow ends at the end of the function call (line 23), or am I wrong? |
@manuels Neither. It appears to be a bug in generators arising because #![feature(conservative_impl_trait, generators, generator_trait)]
extern crate futures;
use std::ops::{ Generator, GeneratorState };
use futures::{ Async, future, Future };
struct Foo {
i: u8,
}
impl Foo {
fn i<'a>(&'a mut self) -> impl Future<Item = u8, Error = ()> + 'a {
future::ok(self.i)
}
}
fn run<'a>(foo: &'a mut Foo) -> impl Generator<Yield = (), Return = Result<u8, ()>> + 'a {
move || {
if false {
yield
}
let _ = {
let mut f = foo.i();
loop {
let poll = f.poll();
match poll {
Ok(Async::Ready(i)) => break i,
Ok(Async::NotReady) => yield,
_ => unreachable!(),
}
}
};
{
let mut f = foo.i();
let poll = f.poll();
match poll {
Ok(Async::Ready(i)) => Ok(i),
_ => unreachable!(),
}
}
}
}
fn main() {
let mut foo = Foo { i: 0 };
let mut g = run(&mut foo);
match g.resume() {
GeneratorState::Complete(Ok(i)) => println!("{}", i),
_ => unreachable!(),
}
} (It can probably be simplified much more by getting rid of the futures crate, but I don't have the time atm.) Either removing the |
The equivalent workaround for fn foo<'a>() -> impl Stream<...> + 'a {
async_stream_block! {
/* Whatever you would've written inside an #[async_stream] function */
}
} |
Outstanding work on all of this! In the name of getting some feedback out there, in respect to ergonomics, I would say that having references supported in When creating libraries or simply creating internal types, encapsulation is going to lead to interfaces with lots of So, where exactly does the limitation come from at this point? Is this an issue with futures, the generator/coroutine implementation, or just the macros themselves? Once again, outstanding work on this! Keep up the good work. |
The nasty bug for the workaround is fixed if you use |
PR #63 will resolve this issue, including support for elided lifetimes. |
Closing because it should be fixed in 0.2. |
(The README alludes to ongoing work/thought on this. I figured there should be an issue to track it.)
Right now, borrowed arguments in
#[async]
functions are no bueno. Life would be easier if they were supported, as the alternate is toBox
arguments or somehow convert them to owned.The text was updated successfully, but these errors were encountered: