I try to create a transaction object from a parent connection being in async context. Here is a distilled situation:
use std::fmt::Debug;
use std::future::Future as StdFuture;
use std::pin::Pin;
use std::result::Result as StdResult;
#[derive(Debug)]
enum Error {
Unknown,
}
type Result<T> = StdResult<T, Error>;
type Future<'a, T> = Pin<Box<dyn StdFuture<Output = T> + Send + 'a>>;
trait DataConn<'c> {
type Tx: DataTx<'c>;
fn begin(&'c mut self) -> Future<Result<Self::Tx>>;
}
trait DataTx<'c> {
type Tx: DataTx<'c>;
fn begin(&'c mut self) -> Future<Result<Self::Tx>>;
}
async fn test_transactions<'c>(mut conn: impl DataConn<'c> + 'c)
{
let tx = conn.begin().await.unwrap();
}
As result I get the following error:
error[E0597]: `conn` does not live long enough
--> src/lib.rs:29:14
|
27 | async fn test_transactions<'c>(mut conn: impl DataConn<'c> + 'c)
| -- lifetime `'c` defined here
28 | {
29 | let tx = conn.begin().await.unwrap();
| ^^^^^^^^^^^^
| |
| borrowed value does not live long enough
| argument requires that `conn` is borrowed for `'c`
30 | }
| - `conn` dropped here while still borrowed
I don't get why the connection is going to be dropped before the transaction we create, while both have the same 'c
lifetime. What do I miss here?
UPDATE: Some suggestions work being standalone, but cause compilation errors for my trait implementation:
struct SqliteConn<'c> {
conn: sqlx::SqliteConnection,
phantom: PhantomData<&'c ()>,
}
pub struct SqliteTx<'c> {
tx: Transaction<'c, Sqlite>,
}
impl<'c> DataConn<'c> for SqliteConn<'c> {
type Tx = SqliteTx<'c>;
fn begin(&'c mut self) -> Future<Result<Self::Tx>> {
Box::pin(async move {
Ok(SqliteTx {
tx: Connection::begin(&mut self.conn).await?,
})
})
}
}