Keeping rusqlite connection and transaction inside same structure

I guess I'm not understanding what rusqlite::Transaction::new() is doing with connection.

Is this possible?

thanks!

The return value of Transaction::new borrows from the Connection you pass in:

    fn new(conn: &'a mut Connection, behavior: TransactionBehavior) -> Result<Transaction<'a>>

You can't store a value x and another value y that borrows from x in the same struct. The compiler prevents this because moving the struct would (or could) invalidate the borrowing value, and in Rust it's assumed that all values remain valid after moving.

2 Likes

It is not possible.

Rust's model of moves and borrow checking model does not support any case of a "self-referential struct".

Well that's not completely exact.

If using an async function, the compiler will generate a self-referential struct for you.

I use this together with genawaiter to implement a cache for "view types" that are both costly to produce but unfortunately tied to a another resource (the drawbacks of "zero-copy parsing"). So I put the view type and the resource it borrows in the same async function driven by genawaiter, and store the resulting coroutine.

To call "methods" on the coroutine generated by genawaiter I use resume with a message corresponding to the called method and it's argument, and this yields the return value.

It is a bit cursed (particularly because genawaiter seems to gobble the value passed to the first call to resume_with), but it works and is fully safe (excluding the unsafety from genawaiter itself). It is also a very natural way to express the whole "I have a borrow that's frozen in this coroutine that I will eventually resume".

Regarding overhead, there's the allocation to make the coroutine box-pinned, and the fact that calling a function now goes through an enum of messages, which means that the size of a message is the max of the sizes of its variants.