If I put an explicit lifetime on the receiver of a method, like &'a mut self, then calls to that method extend the mutable borrow for the lifetime of self:
The larger problem I'm trying to solve is implementing a doubly-linked list with typed_arena::Arena. Here's a slightly more detailed example:
This does work, but now the type signatures don't accurately reflect that's going on w/r/t mutability. And I don't really grok why its necessary. Any suggestions here?
If we substitute in the type of Self, we get that the parameter to test is of type &'t mut A<'t>. It is nearly always incorrect to use the same lifetime parameter for an &mut and what the &mut refers to — it produces exactly the effect you're seeing, because of the simultaneous constraints:
&'t mut requires the thing being referred to is guaranteed to exist for lifetime 't.
A<'t> requires that the A<'t>does not outlive't.
Putting these two constraints together in the form &'t mut A<'t> causes the borrow checker to conclude that the A is borrowed for the rest of its existence.
More generally, using the same lifetime for an &mut reference and something else will usually be over-constraining. They should get their own independent lifetimes.
Notably, constructing recursive types in an arena is an exception where coming across such a reference type can make sense. It has got to be treated almost like the owner of the data though, as you cannot share/duplicate such mutable references.
Doubly linked list would mean shared references are needed and then interior mutability e. g. via RefCell seems unavoidable. I cannot see the code examples of OP though because they appear to be on a website that forces you to create an account in order to see the linked contents.
Rust uses lifetimes to statically prove that no exclusive borrow (&mut) to some memory is alive at the same point as any other access (among other things). We have the terms "mutable borrow" and "interior mutability", but probably would be better off with the terms "exclusive borrow" and "shared mutability".
A doubly-linked list made out of &mut references would have multiple live &mut to the same memory, which is instant UB in Rust.
RefCell uses runtime checks to achieve the same exclusivity guarantees.