impl Итератор не работает для итератора с несколькими параметрами времени жизни - PullRequest
2 голосов
/ 26 апреля 2020

У меня есть код, который выглядит (немного) примерно так:

struct OutputIterator<'r, 'i: 'r> {
    input_handler: &'r mut InputHandler<'i>
}

impl<'r, 'i> Iterator for OutputIterator<'r, 'i> {
    type Item = i32;

    fn next(&mut self) -> Option<Self::Item> {
        self.input_handler.inputs.next().map(|x| x * 2)
    }
}

struct InputHandler<'a> {
    inputs: Box<dyn Iterator<Item = i32> + 'a>
}

impl<'a> InputHandler<'a> {
    fn outputs<'b>(&'b mut self) -> OutputIterator<'b, 'a> {
        OutputIterator { input_handler: self }
    }
}

fn main() {
    let mut input_handler = InputHandler {
        inputs: Box::new(vec![1,2,3,4,5].into_iter())
    };
    for output in input_handler.outputs() {
        println!("{}", output);
    }
}

По сути, пользователь может предоставить итератор входных данных, а затем получить итератор выходных данных (в моем реальном коде Соединение между входами и выходами намного сложнее, включая множество внутренних состояний. Несколько входов могут go к одному выходу или наоборот).

Это работает, но я бы хотел изменить его, используя impl Iterator чтобы скрыть тип OutputIterator и упростить замену возвращаемого типа при тестировании с фальшивкой. Моя лучшая попытка изменить это на InputHandler:

impl<'a> InputHandler<'a> {
    fn outputs<'b>(&'b mut self) -> impl Iterator<Item = i32> + 'b {
        OutputIterator { input_handler: self }
    }
}

К сожалению, меня это достает: error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds

Есть ли способ заставить эту работу работать? Для интерфейса важно, чтобы InputHandler использовал итератор с некоторым временем жизни, и это, очевидно, должно как-то передаваться в OutputIterator, но я действительно хотел бы абстрагировать эти детали от вызывающего. В принципе, вызывающему абоненту нужно только заботиться о том, чтобы входные данные Iterator и InputHandler пережили OutputIterator, поэтому я думаю, что логическое время жизни, ограниченное OutputIterator, здесь меньше из этих двух? Любая ясность относительно того, почему эта ошибка происходит или как ее исправить, была бы великолепна!

В случае, если это поможет, вот ржавчина с кодом в ней.

1 Ответ

1 голос
/ 27 апреля 2020

Использование обходного пути от https://github.com/rust-lang/rust/issues/34511#issuecomment -373423999 , через { ссылка }:

trait Captures<'a> {}
impl<'a, T: ?Sized> Captures<'a> for T {}

impl<'a> InputHandler<'a> {
    fn outputs<'b>(&'b mut self) -> impl Iterator<Item = i32> + Captures<'a> + 'b {
        OutputIterator { input_handler: self }
    }
}
...