I want to write the following function:
fn foo<\'a, \'b, \'c>(rr1: &\'a mut &\'c mut u32, rr2: &\'b mut &\'c mut u32) {
*rr1 = *rr2
You cannot dereference a &'b mut &'c mut u32 and get a &'c mut u32 because:
&mut references are not trivially copiable, so you can't copy the &'c mut u32; and&'c mut u32 (which would leave the outer reference dangling).Instead, the compiler reborrows the u32 with the outer lifetime, 'b. This is why you get an error message that data from rr2 flows into rr1.
If foo were allowed to compile, you could use it to get two &mut references to the same u32, which is forbidden by the rules of references:
let (mut x, mut y) = (10, 20);
let mut rx = &mut x;
let mut ry = &mut y;
foo(&mut rx, &mut ry); // rx and ry now both refer to y
std::mem::swap(rx, ry); // undefined behavior!
If I require that 'b outlives 'c, it works
Because 'c must already outlive 'b¹, if you require that 'b also outlives 'c, it follows that 'c = 'b. The updated signature is equivalent to this:
fn foo<'a, 'b>(rr1: &'a mut &'b mut u32, rr2: &'b mut &'b mut u32)
That is, you have unified 'c and 'b, and now there's no problem borrowing a &'b mut u32 from rr2 because the inner and outer lifetimes both live for 'b. However, the compiler now won't let you write the broken code in the example I gave earlier, since ry is already borrowed for its entire lifetime.
Interestingly, if you make the inner reference non-mut, it also works:
fn foo<'a, 'b, 'c>(rr1: &'a mut &'c u32, rr2: &'b mut &'c u32) {
*rr1 = *rr2;
}
This is because & references are Copy, so *rr2 is not a reborrow, but actually just a copy of the inner value.
For more information, read:
¹ It might not be obvious why 'c outlives 'b when there is no explicit 'c: 'b bound. The reason is because the compiler assumes that the type &'b mut &'c mut u32 is well-formed. Well-formedness can become complex (see RFC 1214) but in this case it just means you can't have a reference that's valid for longer ('b) than the thing it references ('c).