我是否错误地实现了IntoIterator作为参考,或者这是应该报告的Rust错误? [英] Am I incorrectly implementing IntoIterator for a reference or is this a Rust bug that should be reported?

查看:54
本文介绍了我是否错误地实现了IntoIterator作为参考,或者这是应该报告的Rust错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

进一步介绍根据IntoIterator 的示例="nofollow noreferrer"> Rust书,我还尝试根据

Furthering the example of implementing IntoIterator for a wrapped vector as per the Rust book, I am also trying to implement IntoIterator for a reference to the wrapper, as per the following code (Playground link):

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 中使用它的过程不会出现以下错误:

Although the implementation compiles, the attempt to use it in main doesn't with the following error:

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 的方式大大简化了(重复)类型,但归结为仅显示问题.

This code is greatly simplified from what I would actually want to use as to using only 'static lifetimes, using an existing contained type, and using i32 for the inner (iterated) type, but it is boiled down to show just the problem.

已接受的答案解决了问题的第一部分,即不使用'static 并使用带有特征的 +'a .我仍然对实际代码有问题,这是一个 LazyList 实现.我已将其发布为我错误地实现IntoIterator以引用LazyList实现,还是这是Rust的错误?.

The accepted answer solves the first part of the problem as to not using 'static and using + 'a with traits. I still am having a problem with the actual code, which is a LazyList implementation. I've posted that as Am I incorrectly implementing IntoIterator for a reference to a LazyList implementation or is this a Rust bug?.

推荐答案

您已经正确实现了迭代器,以引用在整个程序中有效的 VecWrapper > — 静态"生存期.

You have correctly implemented the iterator for references to VecWrappers that live for the entire length of the program — the 'static lifetime.

您是否希望有一个通用的生存期.然后,将为每个实例提供唯一的具体生命期.通常,我们很懒,只是给这个生命起个名字'a :

Chances are you want to have a generic lifetime. That lifetime will then be provided a concrete lifetime, unique to each instantiation. Usually, we are lazy and just give this lifetime the name '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迭代器< Item =&'a i32>+'a> - +'a .这是必需的,因为特征对象将假定没有内部值引用任何寿命短的东西.
  • Item 类型现在为&'a i32 .
  • 在许多地方都声明了通用生命周期,并在许多地方都提供了通用生命周期(<'a> ).
  • Box<dyn Iterator<Item = &'a i32> + 'a> - + 'a was added. This is needed because a trait object will assume that there are no interior values that reference anything with a short lifetime.
  • The Item type is now &'a i32.
  • A generic lifetime is declared in many places and provided in many others (<'a>).

另请参阅:

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

Normally, there wouldn't be a reason to use a trait object here. I'd just embed the iterator directly:

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

这避免了进行任何间接调用的需要,这种情况在任何情况下都不会被使用.此外,它更明显地将生命周期结合在一起.

This avoids the need to have any indirection, which is unused in this case anyway. Additionally, it more obviously couples the lifetimes.

这篇关于我是否错误地实现了IntoIterator作为参考,或者这是应该报告的Rust错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆