Почему эти точные времена жизни необходимы для компиляции кода? - PullRequest
0 голосов
/ 08 июня 2018

Я пишу синтаксический анализатор и мне нужен взгляд из итератора, но я не хотел использовать черту Peekable.Вместо этого я использовал обертку для итератора.Я придумал что-то вроде этого, опуская все ненужное:

struct Wrapper<'a> {
    it: &'a mut Iterator<Item = &'a String>,
}

pub trait DoSomething {
    fn do_something(self);
}

impl<'a, T> DoSomething for T
where
    T: IntoIterator<Item = &'a String>,
{
    fn do_something(self) {
        let mut it = self.into_iter();
        let throwaway = Wrapper { it: &mut it };
    }
}

Это не компилируется с:

error[E0309]: the associated type `<T as std::iter::IntoIterator>::IntoIter` may not live long enough
  --> src/main.rs:15:39
   |
15 |         let throwaway = Wrapper { it: &mut it };
   |                                       ^^^^^^^
   |
   = help: consider adding an explicit lifetime bound `<T as std::iter::IntoIterator>::IntoIter: 'a`...
note: ...so that the type `<T as std::iter::IntoIterator>::IntoIter` is not borrowed for too long
  --> src/main.rs:15:39
   |
15 |         let throwaway = Wrapper { it: &mut it };
   |                                       ^^^^^^^

error[E0309]: the associated type `<T as std::iter::IntoIterator>::IntoIter` may not live long enough
  --> src/main.rs:15:39
   |
15 |         let throwaway = Wrapper { it: &mut it };
   |                                       ^^^^^^^
   |
   = help: consider adding an explicit lifetime bound `<T as std::iter::IntoIterator>::IntoIter: 'a`...
note: ...so that the type `<T as std::iter::IntoIterator>::IntoIter` will meet its required lifetime bounds
  --> src/main.rs:15:39
   |
15 |         let throwaway = Wrapper { it: &mut it };
   |                                       ^^^^^^^

Хотя я не понимаю, почему это необходимо (вопрос 1),Я добавил T::IntoIter: 'a к предложению where в impl.Это терпит неудачу с:

error[E0597]: `it` does not live long enough
  --> src/main.rs:16:44
   |
16 |         let throwaway = Wrapper { it: &mut it };
   |                                            ^^ borrowed value does not live long enough
17 |     }
   |     - borrowed value only lives until here
   |
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 9:1...
  --> src/main.rs:9:1
   |
9  | / impl<'a, T> DoSomething for T
10 | | where
11 | |     T: IntoIterator<Item = &'a String>,
12 | |     T::IntoIter: 'a,
...  |
17 | |     }
18 | | }
   | |_^

Я также не понимаю, почему it не живет достаточно долго, поскольку порядок освобождения должен быть throwaway, а затем it.Использование второго времени жизни 'b также не работает ни с 'a: 'b, ни с 'b: 'a (я был расстроен и пробовал каждую комбинацию).

Единственное, что помогло, это разделить время жизниссылка на Итератор и содержащиеся в ней ссылки и связанные с ними (не нужно указывать время жизни T::IntoIter):

struct Wrapper<'a, 'b: 'a> {
    it: &'a mut Iterator<Item = &'b String>,
}

Почему?

Имеет смысл сказать: «Ссылки на элементы имеютжить по крайней мере столько же, сколько указано в итераторе », но я не могу понять, почему они не могут быть одинаковыми и почему сообщения об ошибках намекают на конструкцию Wrapper вместо определения, где менялись времена жизнисовсем не помогло.

Официальная документация по продолжительности жизни показалась мне довольно запутанной.Это не относится к тому, действительно ли аннотации времени жизни что-либо изменяют в скомпилированном коде относительно освобождения или просто помогают статическому анализу, фактически не изменяя реальное время жизни фрагмента памяти.

1 Ответ

0 голосов
/ 09 июня 2018

&'a mut Iterator<Item = &'a String> означает, что время жизни ссылки на итератор и ссылки, возвращаемые итератором, должны быть в состоянии быть унифицированными ('a).

Объявление этого итератора и итераторассылки имеют различное время жизни, позволяющее компилировать код:

struct Wrapper<'i, 's: 'i> {
    it: &'i mut Iterator<Item = &'s String>,
}

Нет необходимости добавлять T::IntoIter: 'a.

См. также:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...