This odd bit of code emits an error from do_the_thing()
saying T
does not live long enough:
use std::future::Future;
trait Connection: Send {
type ExecFut<'a>: Future<Output = ()> + Send
where
Self: 'a;
fn transaction<F>(&mut self, _f: F)
where
F: for<'a> FnOnce(&'a mut Self) -> Box<dyn Future<Output = ()> + Send + 'a> + Send,
{
unimplemented!()
}
fn execute<'a>(&'a mut self) -> Self::ExecFut<'a> {
unimplemented!()
}
}
fn do_the_thing<T: Connection>(connection: &mut T) {
connection.transaction(|conn| {
Box::new(async move {
conn.execute().await;
})
});
}
error[E0310]: the parameter type `T` may not live long enough
--> src/main.rs:22:9
|
22 | / Box::new(async move {
23 | | conn.execute().await;
24 | | })
| |__________^ ...so that the type `T` will meet its required lifetime bounds
|
help: consider adding an explicit lifetime bound...
|
20 | fn do_the_thing<T: Connection + 'static>(connection: &mut T) {
| +++++++++
See it on the playground.
As far as I can tell, there should be no implied bound that 'static
is required. Pretty much everything is constrained by 'a
and any lifetimes in T
should always outlive it regardless. Though obviously there might be something I'm missing.
I've also found a few "solutions" that aren't helpful:
- Adding
'static
as the compiler suggests is not reasonable. It can be worked around but there are realConnection
s with non-'static
lifetimes that I would like to use. - For some reason removing the
Send
bound on thedyn Future
makes it pass compilation. This makes zero sense to me. - If I make the function non-generic but use a
Connection
that is not'static
it compiles as well, seemingly contradicting the compiler error.
The above is not real code; the original motivation stems from using AsyncConnection
from the diesel-async crate and similar code structure. However, I hope it is representative of the core issue and that by understanding the problem and potential solutions here, they can be adapted.