Я пишу синтаксический анализатор и мне нужен взгляд из итератора, но я не хотел использовать черту 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
вместо определения, где менялись времена жизнисовсем не помогло.
Официальная документация по продолжительности жизни показалась мне довольно запутанной.Это не относится к тому, действительно ли аннотации времени жизни что-либо изменяют в скомпилированном коде относительно освобождения или просто помогают статическому анализу, фактически не изменяя реальное время жизни фрагмента памяти.