如何解决实现流迭代器的生命周期问题

时间:2018-01-03 15:09:04

标签: iterator rust

不清楚链接问题的重复

这个问题是关于返回对所拥有的struct的成员的引用,而不是关于在同一个对象上存储对拥有值的引用。

我希望得到一些解释,或者对特定情况下发生的事情提供一些提示。

我使用streaming iterators library构建运行时管道,其中在编译时不知道确切的迭代器类型。例如,我想构建一个像

这样的管道
__dict__

为了有效地做到这一点,在迭代器中借用切片似乎很重要。我最好的尝试是创建一个迭代器,gzip解压缩由另一个迭代器传入的read a file > gunzip it > parse the contents > extract fields in a playground

产生的错误是:

[u8]

来自图书馆的an example

error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
  --> src/main.rs:48:50
   |
48 |         self.reader = gzip::Decoder::new(self.it.next().unwrap()).ok();
   |                                                  ^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 47:5...
  --> src/main.rs:47:5
   |
47 | /     fn advance(&mut self) { 
48 | |         self.reader = gzip::Decoder::new(self.it.next().unwrap()).ok();
49 | |     }
   | |_____^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:48:42
   |
48 |         self.reader = gzip::Decoder::new(self.it.next().unwrap()).ok();
   |                                          ^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 44:1...
  --> src/main.rs:44:1
   |
44 | / impl<'a> StreamingIterator for GunzipIter<'a> {
45 | |     type Item = gzip::Decoder<&'a [u8]>;
46 | |     
47 | |     fn advance(&mut self) { 
...  |
50 | |     fn get(&self) -> Option<&gzip::Decoder<&'a [u8]>> { Some(&(self.reader.unwrap())) }
51 | | }
   | |_^
note: ...so that expression is assignable (expected std::option::Option<gzip::Decoder<&'a [u8]>>, found std::option::Option<gzip::Decoder<&[u8]>>)
  --> src/main.rs:48:23
   |
48 |         self.reader = gzip::Decoder::new(self.it.next().unwrap()).ok();
   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

这编译得很好,但是一个更接近我的用例的类似例子并不是:

use streaming_iterator::StreamingIterator;

pub struct FakeStreamingIterator<'a, I, T>
where
    I: Iterator<Item = &'a &'a T>,
    T: 'a + ?Sized,
{
    inner: Box<I>,
    current: Option<&'a &'a T>,
}

impl<'a, I, T> FakeStreamingIterator<'a, I, T>
where
    I: Iterator<Item = &'a &'a T>,
    T: ?Sized,
{
    fn new(inner: I) -> FakeStreamingIterator<'a, I, T> {
        FakeStreamingIterator {
            inner: Box::new(inner),
            current: None,
        }
    }
}

impl<'a, I, T> StreamingIterator for FakeStreamingIterator<'a, I, T>
where
    I: Iterator<Item = &'a &'a T>,
    T: ?Sized,
{
    type Item = T;

    fn advance(&mut self) {
        self.current = self.inner.next();
    }
    fn get(&self) -> Option<&T> {
        self.current.map(|x| *x)
    }
}

错误总是归结为终生不匹配,但我不明白如何解决这个问题。正如我所看到的,主要区别在于:

  • 我持有use streaming_iterator::StreamingIterator; pub struct FakeStreamingIterator<'a> { inner: Box<StreamingIterator<Item = [u8]>>, current: Option<&'a [u8]>, } impl<'a> FakeStreamingIterator<'a> { fn new(inner: Box<StreamingIterator<Item = [u8]>>) -> FakeStreamingIterator<'a> { FakeStreamingIterator { inner: inner, current: None, } } } impl<'a> StreamingIterator for FakeStreamingIterator<'a> { type Item = [u8]; fn advance(&mut self) { self.current = self.inner.next(); } fn get(&self) -> Option<&[u8]> { self.current.map(|x| x) } } 特征,而不是Box类型。这是必需的,因为在编译时不知道父迭代器。
  • 我使用切片而不是参考引用。我不明白为什么会影响生命周期。

在我看来,有两个合乎逻辑的生命周期:

  1. 迭代器的生命周期
  2. 当前切片的生命周期。
  3. 切片寿命必须短于迭代器生存期。我假设有一种情况,Rust可以保证Box没有被调用,而advance(&mut)活着的结果是活跃的借用,但我是不知道如何写这个。

    我已经阅读了很多关于借用和生命的内容,但不了解这种情况的不同。

0 个答案:

没有答案