1 | fn go<'a, 'b>(value: &'a mut &'b mut i32) -> &'b mut i32 {
| ------------------- -----------
| |
| this parameter and the return type are declared with different lifetimes...
2 | *value
| ^^^^^^ ...but data from `value` is returned here
All I'm doing is dereferencing and returning the type with the same lifetime. Why is that not valid?
If your function were accepted then you could duplicate an &mut reference.
let data = 100;
let b = &mut data; // suppose this has lifetime 'b
let borrow1 = go /* <'a1, 'b> */ (&mut b); // borrows b with temporary lifetime 'a1
let borrow2 = go /* <'a2, 'b> */ (&mut b); // borrows b with temporary lifetime 'a2
// borrow1 and borrow2 are now &'b mut i32 to the same data,
// and they have forgotten about 'a1 and 'a2
&mut references are unique references. The dereference operation in go() violates that uniqueness by allowing returning a &'b mut which lives longer than the &'a mut which granted access to it.
@RedDocMD's suggestion will work, by forcing 'a to be the same length as 'b, which ensures the above problem doesn't happen because the lifetimes of borrow1 and borrow2 become equal to their respective (&mut b)s, at which point the usual mutable borrow conflict rules apply.
Another approach which makes the function as general as possible while still succeeding is
Now, 'b can still be longer than 'a, but the returned borrow is only as long as it can be while still preserving uniqueness of &mut references — as long as the input &'a mut.