I am using the rustqlite library for a SQLite database (playground)
use std::ops::Deref;
pub struct Connection {
}
impl Connection {
pub fn transaction(&mut self) -> Transaction {
Transaction::new(self)
}
}
pub struct Transaction<'conn> {
conn: &'conn Connection
}
impl Transaction<'_> {
pub fn new(conn: &mut Connection) -> Transaction {
Transaction{ conn }
}
pub fn commit(mut self) -> Result<(), ()> {
Ok(())
}
}
impl Deref for Transaction<'_> {
type Target = Connection;
#[inline]
fn deref(&self) -> &Connection {
self.conn
}
}
With this implementation, the Transaction object will take the ownership of the Connection object. At the same time, it also implements the Deref trait so we can call all methods from the Transaction struct as from the Connection struct.
The implementation detail is here
From my application code, I want to have a single object that can be represented by either Transaction or Connection. This is necessary because the logic has a flag to decide to use transaction or not. There is a cast to treat the Transaction object as the Connection object:
let conn = create_connection(); // Connection
let tx = conn.transaction(); // Transaction
let conn: &Transaction = &tx; // cast back to Connection type from the Transaction type
However, I don't know how to arrange this code from the application POV with the condition. Here is my pseudocode:
pub fn execute(is_tx: bool) {
// conn will have Connection type
let conn = match is_tx {
true => &create_connection(),
false => {
let x = create_connection().transaction();
let t: &Connection = &x;
t
}
};
// do other things with conn object
}
pub fn create_connection() -> Connection {
Connection{}
}
However, there will be an error
error[E0716]: temporary value dropped while borrowed
--> src/lib.rs:36:21
|
36 | let x = create_connection().transaction();
| ^^^^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
| |
| creates a temporary which is freed while still in use
37 | let t: &Connection = &x;
| -- borrow later used here
|
= note: consider using a `let` binding to create a longer lived value
error[E0597]: `x` does not live long enough
--> src/lib.rs:37:34
|
37 | let t: &Connection = &x;
| ^^ borrowed value does not live long enough
38 | t
| - borrow later used here
39 | }
| - `x` dropped here while still borrowed
I understand the error, but I've tried a couple of workarounds without success, mostly because the Transaction struct takes ownership of the Connection struct. How can I fix this?