Open jonhoo opened 5 years ago
I suspect the answer is no -- cc @rust-lang/wg-async-await -- this might contribute to "not Send/Sync" errors if we're capturing what we shouldn't be
I think my expectation is that the explicit type = impl Trait
version should work. I'm not 100% sure why it doesn't, but I can do some investigation.
Assigning to myself to investigate and document the cause of the issue, at least.
Related to / dupe of https://github.com/rust-lang/rust/issues/42940
I hate bumping issues but... any movement on this? Just ran into it myself in a very similar context
No progress I know of
Note that this bug does not require async to trigger. Playground where this triggered using type_alias_impl_trait
. I'm not sure if/how this is related #42940 (as mentioned in the comment above). Looking through the discussion there, I couldn't find any mentions of the error returned by the compiler.
Reproduced with a more minimal example: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=319e66180308bede359b022cda8ed0bf
#![feature(type_alias_impl_trait)]
type Ty = impl Fn();
fn run<E>(_: E) -> Ty {
|| ()
}
Compiling playground v0.0.1 (/playground)
error: type parameter `E` is part of concrete type but not used in parameter list for the `impl Trait` type alias
--> src/lib.rs:6:5
|
6 | || ()
| ^^^^^
error: could not compile `playground` due to previous error```
Here's the minimum async
example of this problem:
#![feature(type_alias_impl_trait)]
use std::future::Future;
type Deferred = impl Future<Output = ()> + 'static;
fn future_out<F>(_: F) -> Deferred {
async move { }
}
error: type parameter `F` is part of concrete type but not used in parameter list for the `impl Trait` type alias
--> src/lib.rs:8:5
|
8 | async move { }
| ^^^^^^^^^^^^^^
error: could not compile `playground` (lib) due to previous error
Notably, there's discussion over in #107645 about the possibility of limiting TAIT to exclude defining uses where the TAIT appears in argument position in the function signature. If that were to be adopted, one plausible workaround would look like this:
#![feature(type_alias_impl_trait)]
use std::future::Future;
use tokio::sync::oneshot::Sender;
type Deferred = impl Future<Output = ()> + 'static;
fn sends_future_kludge<F: Future<Output = ()> + 'static>(f: F) -> Deferred {
async move { f.await }
}
fn sends_future(tx: Sender<Deferred>) {
let _ = tx.send(sends_future_kludge(async move {}));
}
However, that workaround would be blocked on this issue.
I'd like to write the following code:
In particular, I would like to have the
impl Trait
returned bybaz
not be tied to the lifetime of its&str
argument. Sinceimpl Trait
captures the lifetimes of all generic arguments (as per RFC 1951), I can't write the code this way though. So instead, I triedHowever, with this, I get the error:
This seems odd, since
Q
is (intentionally) not used in theasync
block. I can work around this by adding anasync fn
and calling that instead of usingasync move
, but that seems like an odd hack:Is it intentional that the
async
block "captures"Q
here, even though it never contains aQ
?