Почему это & ​​время жизни отличается от & mut?

Я создаю пользовательскую структуру данных в Rust и пытаюсь реализовать для нее итераторы. Следуя примеру встроенных коллекций (LinkedList, Vec и т. Д.), Я создал структуру IntoIter, которая выполняет итерацию по принадлежащей коллекции, структуру Iter, которая выполняет итерацию по заимствованной коллекции, и структуру IterMut, которая выполняет итерацию по изменяемой коллекции. заимствованная коллекция.

Мне удалось реализовать первые два итератора, но у меня возникли проблемы с обслуживанием средства проверки заимствований с помощью IterMut. Я сократил свой код до минимума воспроизведения и заменил свою собственную структуру данных на Vec<Option<T>>:

pub struct IterMut<'a, T: 'a> {
    list: &'a mut Vec<Option<T>>,
}

impl<'a, T> Iterator for IterMut<'a, T> {
    type Item = &'a mut T;

    fn next(&mut self) -> Option<&'a mut T> {
        let head_node = &mut self.list[0];
        // convert &mut Option<T> to Option<&mut T>
        head_node.as_mut()
    }
}

Пример на игровой площадке

Не удается скомпилировать с

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
  --> src/main.rs:23:24
   |
23 |   let head_node = &mut self.list[0];
   |                        ^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 22:2...
  --> src/main.rs:22:2
   |
22 | /  fn next(&mut self) -> Option<&'a mut T> {
23 | |   let head_node = &mut self.list[0];
24 | |   // convert &mut Option<T> to Option<&mut T>
25 | |   head_node.as_mut()
26 | |  }
   | |__^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:23:24
   |
23 |   let head_node = &mut self.list[0];
   |                        ^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 19:1...
  --> src/main.rs:19:1
   |
19 | / impl<'a, T> Iterator for IterMut<'a, T> {
20 | |  type Item = &'a mut T;
21 | |
22 | |  fn next(&mut self) -> Option<&'a mut T> {
...  |
26 | |  }
27 | | }
   | |_^
note: ...so that expression is assignable (expected std::option::Option<&'a mut T>, found std::option::Option<&mut T>)
  --> src/main.rs:25:3
   |
25 |   head_node.as_mut()
   |   ^^^^^^^^^^^^^^^^^^

Что меня действительно смущает, так это то, что этот код почти идентичен коду, который я использовал для Iter, который успешно компилируется:

pub struct Iter<'a, T: 'a> {
    list: &'a Vec<Option<T>>,
}

impl<'a, T> Iterator for Iter<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<&'a T> {
        let head_node = &self.list[0];
        // convert &Option<T> to Option<&T>
        head_node.as_ref()
    }
}

Я знаю, что & и &mut - две разные вещи, но я думал, что их время жизни будет рассчитываться одинаково. Мое первое предположение заключалось в том, что as_ref() должно чем-то отличаться от as_mut(), но, похоже, нет разницы в исходном коде их реализаций (as_ref, as_mut).

На что жалуется контролер заемщиков?


person Brian    schedule 18.12.2017    source источник
comment
Ваш сокращенный пример довольно хорошо показывает проблему. Возвращая одну и ту же изменяемую ссылку несколько раз (&mut self.list[0]), вы нарушите правила Rust для ссылок! Вот повторяющийся ответ, примененный к вашему коду.   -  person Shepmaster    schedule 18.12.2017