Умный конструктор для итератора со ссылкой на замыкание внутри - PullRequest
0 голосов
/ 26 августа 2018

Рассмотрим следующий код для (очень упрощенного) итератора со ссылкой на замыкание внутри:

struct IteratorState<'a, T: 'a + Fn(i32) -> i32> {
    closure: &'a T,
}

impl<'a, T: 'a + Fn(i32) -> i32> Iterator for IteratorState<'a, T> {
    type Item = i32;

    fn next(&mut self) -> Option<i32> {
        None
    }
}

Он компилируется, и я могу напрямую создать IteratorState s.Однако мне также нужен умный конструктор, чтобы скрыть некоторые детали реализации (не показано в MCVE).Следующая попытка не компилируется:

fn mk_iter<'a, T: Fn(i32) -> i32>(closure: &'a T) -> impl Iterator<Item = i32> {
    IteratorState { closure }
}

Ошибка:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
  --> src/lib.rs:14:5
   |
14 |     IteratorState { closure }
   |     ^^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 13:1...
  --> src/lib.rs:13:1
   |
13 | fn mk_iter<'a, T: Fn(i32) -> i32>(closure: &'a T) -> impl Iterator<Item = i32> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
  --> src/lib.rs:14:21
   |
14 |     IteratorState { closure }
   |                     ^^^^^^^
   = note: but, the lifetime must be valid for the static lifetime...
note: ...so that return value is valid for the call
  --> src/lib.rs:13:54
   |
13 | fn mk_iter<'a, T: Fn(i32) -> i32>(closure: &'a T) -> impl Iterator<Item = i32> {
   |                                                      ^^^^^^^^^^^^^^^^^^^^^^^^^

Мне кажется, я понимаю, в чем проблема: нет никакой гарантии, что построено IteratorState не переживет содержащуюся ссылку (пожалуйста, исправьте меня, если я ошибся), но я не совсем уверен, как это исправить.

1 Ответ

0 голосов
/ 26 августа 2018

Синтаксис impl Trait поддерживает добавление времени жизни к возвращаемому типу:

fn mk_iter<'a, T: Fn(i32) -> i32>(closure: &'a T) -> impl Iterator<Item = i32> + 'a {
      //                                                                  here ^^^^
    IteratorState {
        closure
    }
}

( ссылка на игровую площадку )

...