Вы не можете разыменовать a &'b mut &'c mut u32
и получать &'c mut u32
, потому что:
&mut
ссылки не могут быть скопированы, поэтому вы не можете copy the &'c mut u32
; и - Вы не можете выйти за пределы ссылки, поэтому вы также не можете переместить
&'c mut u32
(что повлечет за собой зависание внешней ссылки).
Вместо этого компилятор перезагружает u32
с внешним временем жизни, 'b
. Вот почему вы получаете сообщение об ошибке, согласно которому данные из rr2
поступают в rr1
.
Если foo
разрешено компилировать, вы можете использовать его для получения двух &mut
ссылок на один и тот же u32
, что запрещено правилами ссылок:
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!
Если мне требуется, чтобы 'b переживало' c, это работает
Потому что 'c
должен уже пережить 'b
, если вам требуется, чтобы 'b
также пережил 'c
, из этого следует, что 'c
= 'b
. Обновленная подпись эквивалентна этому:
fn foo<'a, 'b>(rr1: &'a mut &'b mut u32, rr2: &'b mut &'b mut u32)
То есть вы объединили 'c
и 'b
, и теперь нет проблем с заимствованием &'b mut u32
из rr2
, потому что внутренний и внешний обе жизни живут за 'b
. Однако теперь компилятор не позволит вам написать испорченный код в примере, который я дал ранее, поскольку ry
уже заимствован на весь срок его жизни.
Интересно, если вы сделаете внутреннюю ссылку не- mut
, это также работает:
fn foo<'a, 'b, 'c>(rr1: &'a mut &'c u32, rr2: &'b mut &'c u32) {
*rr1 = *rr2;
}
Это потому, что ссылки &
равны Copy
, поэтому *rr2
не является повторным заимствованием, а фактически копией внутреннего значения. Для получения дополнительной информации читайте Почему связь времени жизни имеет значение только с изменяемыми ссылками?