Почему добавление жизни к признаку с помощью оператора плюс (Iterator <Item = & Foo> + a) необходимо?

Я применяю замыкание к итератору и хочу использовать стабильный, поэтому хочу вернуть упакованный Iterator. Очевидный способ сделать это заключается в следующем:

struct Foo;

fn into_iterator(myvec: &Vec<Foo>) -> Box<dyn Iterator<Item = &Foo>> {
    Box::new(myvec.iter())
}

Это не помогло, потому что контролер заимствований не может определить соответствующий срок жизни.

После некоторых исследований я обнаружил, как правильно вернуть итератор (или любую другую черту)?, что привело меня к добавлению + 'a:

fn into_iterator<'a>(myvec: &'a Vec<Foo>) -> Box<dyn Iterator<Item = &'a Foo> + 'a> {
    Box::new(myvec.iter())
}

Но я не понимаю,

  • Что это делает
  • А зачем это нужно тут

Ответ 1

Есть одна вещь, которую легко упустить из виду: если у вас есть черта Bar и вы хотите иметь объект в штучной упаковке Box<dyn Bar>, компилятор автоматически добавляет ограничение времени жизни 'static (как указано в RFC 599). Это означает, что Box<dyn Bar> и Box<dyn Bar + 'static> эквивалентны!

В вашем случае компилятор автоматически добавляет статическую границу, так что это...

fn into_iterator(myvec: &Vec<Foo>) -> Box<dyn Iterator<Item = &Foo>>

... эквивалентно этому:

fn into_iterator(myvec: &Vec<Foo>) -> Box<dyn Iterator<Item = &Foo> + 'static>

Теперь правила выбора времени жизни включаются и "соединяют" два интервала времени жизни, так что приведенный выше код эквивалентен:

fn into_iterator<'a>(myvec: &'a Vec<Foo>) -> Box<dyn Iterator<Item = &'a Foo> + 'static>

Но тип Iter<'a, Foo> (определенный тип итератора для Vec<Foo>), очевидно, не удовлетворяет границе 'static (потому что он заимствует Vec<Foo>)! Таким образом, мы должны сказать компилятору, что мы не хотим привязку по умолчанию 'static, указав нашу собственную границу времени жизни:

fn into_iterator<'a>(myvec: &'a Vec<Foo>) -> Box<dyn Iterator<Item = &Foo> + 'a>

Теперь компилятор знает, что объект признака действителен только на время жизни 'a. Обратите внимание, что нам не нужно явно аннотировать время жизни ассоциированного типа Item! Правила пожизненного выбора заботятся об этом.