我是否错误地实现了 IntoIterator 作为参考,或者这是一个应该报告的 Rust 错误?

Am I incorrectly implementing IntoIterator for a reference or is this a Rust bug that should be reported?

根据 the Rust book, I am also trying to implement IntoIterator for a reference to the wrapper, as per the following code (Playground link):

进一步实现包装向量 IntoIterator 的示例
struct VecWrapper(Vec<i32>);

impl VecWrapper {
    fn iter(&'static self) -> Iter {
        Iter(Box::new(self.0.iter()))
    }
}

struct Iter(Box<Iterator<Item = &'static i32>>);

impl Iterator for Iter {
    type Item = &'static i32;
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next()
    }
}

impl IntoIterator for &'static VecWrapper {
    type Item = &'static i32;
    type IntoIter = Iter;
    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

fn main() {
    // let test = vec![1, 2, 3]; // obviously, works
    let test = VecWrapper(vec![1, 2, 3]); // not working
    for v in &test {
        println!("{}", v);
    }
}

尽管实现可以编译,但在 main 中使用它的尝试不会出现以下错误:

error[E0597]: `test` does not live long enough
  --> src/main.rs:31:14
   |
31 |     for v in &test {
   |              ^^^^^
   |              |
   |              borrowed value does not live long enough
   |              argument requires that `test` is borrowed for `'static`
...
34 | }
   | - `test` dropped here while still borrowed

这段代码大大简化了我实际想要使用的代码,仅使用 'static 生命周期,使用现有的包含类型,并使用 i32 作为内部(迭代)类型,但它被归结为仅显示问题。


接受的答案解决了关于不使用 'static 和使用 + 'a 的问题的第一部分。我仍然对实际代码有问题,这是一个 LazyList 实现。我已将其发布为 .

您已经正确实现了对 VecWrapper 的引用的迭代器, 在程序的整个长度'static 生命周期中存在。

您可能希望拥有通用的生命周期。然后将为该生命周期提供一个具体的生命周期,对于每个实例化都是唯一的。通常,我们很懒惰,只是给这一生起个名字'a:

struct VecWrapper(Vec<i32>);

impl VecWrapper {
    fn iter(&self) -> Iter {
        Iter(Box::new(self.0.iter()))
    }
}

struct Iter<'a>(Box<dyn Iterator<Item = &'a i32> + 'a>);

impl<'a> Iterator for Iter<'a> {
    type Item = &'a i32;

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

impl<'a> IntoIterator for &'a VecWrapper {
    type Item = &'a i32;
    type IntoIter = Iter<'a>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

fn main() {
    let test = VecWrapper(vec![1, 2, 3]);
    for v in &test {
        println!("{}", v);
    }
}

重要变化:

  • Box<dyn Iterator<Item = &'a i32> + 'a> - 添加了 + 'a。这是必需的,因为 trait 对象 将假设没有内部值引用任何短生命周期的东西。
  • Item 类型现在是 &'a i32
  • 通用生命周期在许多地方声明并在许多其他地方提供 (<'a>)。

另请参阅:


通常情况下,没有理由在这里使用特征对象。我只是直接嵌入迭代器:

struct Iter<'a>(std::slice::Iter<'a, i32>);

这避免了任何间接的需要,无论如何在这种情况下都没有使用。此外,它更明显地耦合了生命周期。