Why does this code:
#[derive(Eq, PartialEq, Ord, PartialOrd)]
enum List<'a> {
Cons(isize, &'a List<'a>),
Nil,
}
fn main() {
use List::*;
use pinus::{prelude::*, sync::PineMap};
let table = PineMap::new();
table.insert(Nil, Nil);
let nil = table.get(&Nil).unwrap();
table.insert(Cons(1, nil), Cons(1, nil));
}
cause this error:
error[E0597]: `table` does not live long enough
--> src/main.rs:12:15
|
12 | let nil = table.get(&Nil).unwrap();
| ^^^^^^^^^^^^^^^ borrowed value does not live long enough
13 | table.insert(Cons(1, nil), Cons(1, nil));
14 | }
| -
| |
| `table` dropped here while still borrowed
| borrow might be used here, when `table` is dropped and runs the `Drop` code for type `PineMap`
I'm using a pinus::sync::PineMap to try to make sure that all references to equivalent instances of List are actually references of the same object in memory. I thought a way to do this would be to have a table mapping List keys to a table-owned instance of List, and I'm trying out PineMap for it because its insert will not move its items in memory (its insert borrows &self not &mut self too) so references to its List values will stay valid, and I can build self-referential items.
Why is table still considered to be borrowed at the end of its scope in my code?
When you get
nilout of the table and put it back into it withCons(1, nil), the type ofnilis a reference that is tied to the lifetime of thetable, and thus the lifetime'aof theLists that you're storing are bound to thetablethat is storing them.The core problem here is that this creates a self-referential struct, which introduces a myriad of problems. You wouldn't be able to call any of the mutable methods either because the
tableis permanently borrowing itself immutably.The specific problem that the compiler is complaining about is that, since the elements hold a reference to the table, when its being dropped the drop logic may try to access data that is in the process of being destroyed, which is not sound.
I encourage you to read about the Drop Check in the Rustonomicon for more info, here's a guiding principle though:
I don't have any workarounds or solutions for you other than you can't do it this way.