|
|
|
|
|
by Animats
3332 days ago
|
|
Think of backpointers as a combination of Rust optional pointers and weak pointers, mostly checked at compile time. The basic rule for backpointers is this: If an type instance A contains a backpointer P1, it must either be a None, or a reference to a type instance B which has exactly one reference P2 to A. Checks required: - P2 cannot be changed when P1 is not None. (Run-time check; the compiler has to recognize when it is necessary.) - P1 can only be set to None or B. (Compile-time check) - P1 must be set to None before B is destroyed. This avoids a dangling pointer. (Compile-time check when possible, otherwise run-time check.) - Borrow checking must treat a borrow using P1 as a borrow of B. These simple rules would maintain the invariant for the backpointer. This allows doubly-linked lists without unsafe code. The backpointer is "weak" and doesn't count as ownership. It's basically weak pointers with a count of either 0 or 1. |
|
It's a slippery slope argument: if you add this, why stop there? Especially if you require run-time checks.
If there was a compelling set of operation that preserved the invariants without run-time checks, and it was expressive, i.e. it covered a large number of cases that you'd otherwise had to put into "unsafe" and it didn't ruin type inference ...