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

Gor*_*ood 1 iterator lifetime rust borrow-checker

进一步IntoIterator按照Rust的书实现包装矢量的示例,我还尝试根据以下代码(Playground链接)实现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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

相对于仅使用'static生命周期,使用现有包含类型以及i32将内部(迭代)类型使用的方式,此代码大大简化了,但是归纳起来仅显示了问题所在。


公认的答案解决了不使用特征'static+ 'a与特征一起使用的问题的第一部分。我仍然对实际代码有疑问,这是一个LazyList实现。我已经发布了该信息,因为我是错误地实现了IntoIterator来引用LazyList实现,还是这是Rust的错误?

She*_*ter 6

你已经正确地实施了以引用迭代器VecWrapper,且s 现场为节目的整个长度 -的'static寿命。

您可能希望拥有一个通用的寿命。然后将为每个实例提供唯一的具体生命期。通常,我们很懒,只是给这辈子起个名字'a

struct VecWrapper(Vec<i32>);

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

struct Iter<'a>(Box<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]); // not working
    for v in &test {
        println!("{}", v);
    }
}
Run Code Online (Sandbox Code Playgroud)

重要更改:

  • Box<Iterator<Item = &'a i32> + 'a>- + 'a已添加。这是必需的,因为特征对象将假定没有内部值引用任何寿命短的内容。
  • Item目前类型&'a i32
  • 通用生命周期在许多地方都有声明,在其他许多地方也有提供(<'a>)。

也可以看看:


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

struct Iter<'a>(std::slice::Iter<'a, i32>);
Run Code Online (Sandbox Code Playgroud)

这就避免了需要任何间接的需求,在这种情况下,这种间接方式还是不可用的。另外,它更明显地将生命周期耦合在一起。