Unexpected "the parameter type X may not live long enough" error in asynchronous functions #95719
Open
Description
opened on Apr 6, 2022
When a Future
is wrapped in an async
block or an async
function, some of its traits are lost, e.g., Send, thus causing various issues.
I tried this code:
#![feature(impl_trait_in_assoc_type)]
use std::future::Future;
pub trait Get: Send + Sync {
type Ret<'a>: Future<Output = usize> + Send + 'a
where
Self: 'a;
fn get<'a>(&'a self) -> Self::Ret<'a>
where
Self: 'a;
}
impl Get for usize {
type Ret<'a> = impl Future<Output = usize> + Send + 'a
where
Self: 'a;
fn get<'a>(&'a self) -> Self::Ret<'a>
where
Self: 'a,
{
async move { *self }
}
}
fn is_send<R, F: Future<Output = R> + Send>(_f: &F) -> bool {
true
}
async fn wrap<G: Get>(g: &G) -> usize {
let fut = g.get();
assert!(is_send(&fut));
fut.await
}
async fn wrap_wrap<G: Get>(g: &G) -> usize {
let fut = wrap(g);
assert!(is_send(&fut)); //~ ERROR the parameter type `G` may not live long enough
fut.await
}
I expected to see no compiler errors: the returned Future
from async fn wrap
should be Send
, because g.get()
is Send
and async fn wrap
only wraps the code in an asynchronous code block.
Instead, this happened: the returned Future
from async fn wrap
is not anymore Send
. Note that the error manifests differently if another lifetime bounds are involved in the trait - lifetime bound not satisfied
when asserting is_send(&fut)
. It's even strange to see lifetime bounds
or may not live long enough
errors when checking the Send
bound.
Meta
rustc --version --verbose
:
rustc 1.59.0 (9d1b2106e 2022-02-23)
binary: rustc
commit-hash: 9d1b2106e23b1abd32fce1f17267604a5102f57a
commit-date: 2022-02-23
host: aarch64-apple-darwin
release: 1.59.0
LLVM version: 13.0.0
Error
error[E0311]: the parameter type `G` may not live long enough
--> tests/test.rs:687:17
|
684 | async fn wrap_wrap<G: Get>(g: &G) -> usize {
| -- help: consider adding an explicit lifetime bound...: `G: 'a +`
...
687 | assert!(is_send(&fut));
| ^^^^^^^ ...so that the type `G` will meet its required lifetime bounds...
|
note: ...that is required by this bound
--> tests/test.rs:674:43
|
674 | fn is_send<R, F: Future<Output = R> + Send>(_f: &F) -> bool {
| ^^^^
error: could not compile `async-trait` due to previous error
Metadata
Assignees
Labels
Area: Generic associated types (GATs)Area: Async & AwaitArea: Lifetimes / regionsArea: Trait systemAsync-await issues that have been triaged during a working group meeting.`#![feature(impl_trait_in_assoc_type)]`Relevant to the compiler team, which will review and decide on the PR/issue.Relevant to the types team, which will review and decide on the PR/issue.Working group: Async & await
Activity