Другое решение, кроме использования 'stati c life - PullRequest
2 голосов
/ 28 марта 2020

Здесь код:

#[derive(Debug, Eq, PartialEq)]
struct Id(u128);

pub struct IdIter(Box<dyn Iterator<Item= Id>>);

impl IdIter {
    pub fn new<I: Iterator<Item= Id>>(tmpl: I) -> Self {
        Self(Box::new(tmpl))
    }
}

impl Iterator for IdIter {
    type Item = Id;

    fn next(&mut self) -> Option<Self::Item> {
        self.0.next()
    }
}

pub trait Link {
    fn iter_id(&self) -> IdIter;
}

pub fn links(it: impl Iterator<Item= impl Link>) -> impl Iterator<Item= Id> {
    it.into_iter().flat_map(|l| l.iter_id())
}

#[cfg(test)]
mod test {
    struct X(u128);

    impl super::Link for X {
        fn iter_id(&self) -> super::IdIter {
            super::IdIter(Box::new(Some(super::Id(self.0)).into_iter()))
        }
    }

    #[test]
    fn test_links() {
        let mut v = super::links([X(1234), X(4321)].into_iter());

        assert_eq!(v.next(), Some(super::Id(1234u128)));
        assert_eq!(v.next(), Some(super::Id(4321u128)));
        assert_eq!(v.next(), None);
    }
}

Детская площадка

Компилятор предлагает использовать время жизни 'stati c для решения проблемы, но это немного излишне .

Я хочу предложить черту (здесь Link), которую итератор этой черты через функцию links дает итератору Id экземпляров. Эта черта используется и как маркерная, поэтому я не могу использовать другую библиотеку.

Как я могу исправить ошибки компилятора?

Ответы [ 2 ]

3 голосов
/ 28 марта 2020

Ваша ошибка может быть уменьшена до следующего:

pub struct IdIter(Box<dyn Iterator<Item=()>>);

impl IdIter {
    pub fn new<I: Iterator<Item=()>>(tmpl: I) -> Self {
        Self(Box::new(tmpl))
    }
}

Ошибка выглядит следующим образом:

error[E0310]: the parameter type `I` may not live long enough
 --> src/lib.rs:5:14
  |
4 |     pub fn new<I: Iterator<Item=()>>(tmpl: I) -> Self {
  |                -- help: consider adding an explicit lifetime bound `I: 'static`...
5 |         Self(Box::new(tmpl))
  |              ^^^^^^^^^^^^^^
  |
note: ...so that the type `I` will meet its required lifetime bounds
 --> src/lib.rs:5:14
  |
5 |         Self(Box::new(tmpl))
  |              ^^^^^^^^^^^^^^

Сначала это неочевидно, но ошибка указывает вам в общем направлении из того, что происходит: Box<dyn Iterator<Item = ()>> в вашей структуре автоматически Box<dyn Iterator<Item = ()> + 'static>, в то время как I не обязательно может быть 'static.

Решение состоит в том, чтобы ввести новое время жизни:

pub struct IdIter<'a>(Box<dyn Iterator<Item = ()> + 'a>);

impl<'a> IdIter<'a> {
    pub fn new<I: Iterator<Item = ()> + 'a>(tmpl: I) -> Self {
        Self(Box::new(tmpl))
    }
}

Детская площадка

0 голосов
/ 28 марта 2020

Компилируется после предоставления IdIter и явного времени жизни и настройки нескольких частей программы. Вот полный пример игровой площадки .

#[derive(Debug, Eq, PartialEq)]
pub struct Id(u128);

pub struct IdIter<'a>(Box<dyn Iterator<Item = Id> + 'a>);

impl<'a> IdIter<'a> {
    pub fn new<I: Iterator<Item = Id> + 'a>(tmpl: I) -> Self {
        Self(Box::new(tmpl))
    }
}

impl Iterator for IdIter<'_> {
    type Item = Id;

    fn next(&mut self) -> Option<Self::Item> {
        self.0.next()
    }
}

pub trait Link {
    fn iter_id(&self) -> IdIter;
}

pub fn links<'a>(it: impl Iterator<Item = &'a (impl Link + 'a)> + 'a) -> impl Iterator<Item = Id> + 'a {
    it.flat_map(Link::iter_id)
}

#[cfg(test)]
mod test {
    struct X(u128);

    impl super::Link for X {
        fn iter_id(&self) -> super::IdIter {
            super::IdIter(Box::new(Some(super::Id(self.0)).into_iter()))
        }
    }

    #[test]
    fn test_links() {
        let mut v = super::links([X(1234), X(4321)].iter());

        assert_eq!(v.next(), Some(super::Id(1234u128)));
        assert_eq!(v.next(), Some(super::Id(4321u128)));
        assert_eq!(v.next(), None);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...