Проблема здесь:
impl<'a> B<'a> {
fn next(&self) -> B {
let mut new = self.clone();
new.0 = new.0 + 1;
new
}
}
Вы не указали время жизни для B
, тип возврата next
.Из-за правил жизненного правила Rust компилятор делает вывод, что вы предполагали следующее:
impl<'a> B<'a> {
fn next<'c>(&'c self) -> B<'c> {
let mut new = self.clone();
new.0 = new.0 + 1;
new
}
}
Что означает, что возвращаемое значение может не пережить self
.Или, другими словами, self
должен жить дольше, чем B
, который возвращается.Учитывая тело функции, это совершенно ненужное требование , потому что эти ссылки независимы друг от друга.И здесь возникает проблема:
for _ in 0..5 {
b = b.next();
}
Вы перезаписываете значение, которое, по мнению заемщика, все еще заимствовано при вызове next()
.Внутри next
мы знаем, что таких отношений нет - аннотации времени жизни не отражают ограничений того, что вы на самом деле делаете.
Так каковы здесь границы времени жизни?
Время жизни ссылок на B
не связано - каждый может существовать без другого.Таким образом, чтобы обеспечить максимальную гибкость для вызывающей стороны, время жизни B
должно отличаться от времени жизни ссылки на self
в next
.
Однако каждыйB
, созданный с помощью next()
, содержит ссылку на того же u32
, что и self
.Таким образом, время жизни параметр , которое вы даете каждому B
, должно быть одинаковым.
Используя явно именованные времена жизни, это результат объединения обеих этих вещей:
impl<'a> B<'a> {
fn next<'c>(&'c self) -> B<'a> {
let mut new = self.clone();
new.0 = new.0 + 1;
new
}
}
Обратите внимание, что - хотя ссылка - self
здесь имеет время жизни 'c
- тип self
равен B<'a>
, где 'a
равенвремя жизни &u32
внутри.Точно так же, как возвращаемое значение.
Но на самом деле, 'c
может быть исключено.Так что это действительно так же, как это:
impl<'a> B<'a> {
fn next(&self) -> B<'a> {
let mut new = self.clone();
new.0 = new.0 + 1;
new
}
}