Lifetime error with self-referential type (redb::WriteTransaction)

You are trying to create a self-referential type by storing a value (self.table = …) that ultimately borrows from self.

@H2CO3 Thanks, I see.

You'll have to redesign your code so that you don't store table in the same type from which it borrows.

Here I try to redesign the code to put table in a different type.

const TABLE: TableDefinition<&'static [u8], &'static [u8]> = TableDefinition::new("test_table");

struct CacheTable<'db,'txn>(Option<Table<'db, 'txn, &'static [u8], &'static [u8]>>);

struct UseTransaction<'db> {
    txn_write: Option<redb::WriteTransaction<'db>>,
}

impl<'db> UseTransaction<'db> {
    fn compute_some_thing(&'db self, cache_table: &mut CacheTable<'db,'_>) -> Result<(), redb::Error> {
        let txn_write = self.txn_write.as_ref().unwrap();
        let table = txn_write.open_table(TABLE)?;
        cache_table.0 = Some(table);
        Ok(())
    }
}

But I fall in the same error than before:

error: lifetime may not live long enough
  --> tests/tests.rs:56:9
   |
53 |     fn compute_some_thing(&self, cache_table: &mut CacheTable<'db,'_>) -> Result<(), redb::Error> {
   |                           -      ----------- has type `&mut CacheTable<'_, '2>`
   |                           |
   |                           let's call the lifetime of this reference `'1`
...
56 |         cache_table.0 = Some(table);
   |         ^^^^^^^^^^^^^ assignment requires that `'1` must outlive `'2`
   |
   = note: requirement occurs because of the type `Table<'_, '_, &[u8], &[u8]>`, which makes the generic argument `'_` invariant
   = note: the struct `Table<'db, 'txn, K, V>` is invariant over the parameter `'db`
   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance

I need to add 'db lifetime to fn compute_some_thing(&'db self ... but I would find myself in the situation of the beginning.

Code/Error with 'db
const TABLE: TableDefinition<&'static [u8], &'static [u8]> = TableDefinition::new("test_table");

struct CacheTable<'db,'txn>(Option<Table<'db, 'txn, &'static [u8], &'static [u8]>>);

struct UseTransaction<'db> {
    txn_write: Option<redb::WriteTransaction<'db>>,
}

impl<'db> UseTransaction<'db> {
    fn compute_some_thing(&'db self, cache_table: &mut CacheTable<'db,'_>) -> Result<(), redb::Error> {
        let txn_write = self.txn_write.as_ref().unwrap();
        let table = txn_write.open_table(TABLE)?;
        cache_table.0 = Some(table);
        Ok(())
    }
}

Error:

error[E0597]: `use_transaction` does not live long enough
  --> tests/tests.rs:65:5
   |
65 |     use_transaction.compute_some_thing(&mut cache_table).unwrap();
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
66 | }
   | -
   | |
   | `use_transaction` dropped here while still borrowed
   | borrow might be used here, when `use_transaction` is dropped and runs the destructor for type `UseTransaction<'_>`

My goal is to be able to store Table somewhere, to reuse it as a reference as needed.