Rust 迭代器的“在编译时没有已知大小”错误?

问题描述

我正在重构 Rust 的 itertools [1] 中的笛卡尔积代码,作为学习 Rust 的一种方式。笛卡尔积由 Iterator I 和 IntoIterator J 形成。IntoIterator J 多次转换为迭代器并迭代。

到目前为止我有下面的代码,这是对itertools源代码中的代码一个修改。最大的变化是指定特定类型 (i8) 而不是使用泛型类型。

struct Product {
    a: dyn Iterator<Item=i8>,a_cur: Option<i8>,b: dyn IntoIterator<Item=i8,IntoIter=dyn Iterator<Item=i8>>,b_iter: dyn Iterator<Item=i8>
}


impl Iterator for Product {

    type Item = (i8,i8);

    fn next(&mut self) -> Option<Self::Item> {
        let elt_b = match self.b_iter.next() {
            None => {
                self.b_iter = self.b.into_iter();
                match self.b_iter.next() {
                    None => return None,Some(x) => {
                        self.a_cur = self.a.next();
                        x
                    }
                }
            }
            Some(x) => x
        };
        match self.a_cur {
            None => None,Some(ref a) => {
                Some((a,elt_b))
            }
        }

    }

}


fn cp(i: impl Iterator<Item=i8>,j: impl IntoIterator<Item=i8>) -> Product {
    
   let p = Product{
       a: i,a_cur: i.next(),b: j,b_iter: j.into_iter()};
   return p

}



fn main() {

    for foo in cp(vec![1,4,7],vec![2,3,9]) {
        println!("{:?}",foo);
    }

}

不幸的是,编译器给出了我无法修复的错误。我已经尝试了编译器建议的修复,但是当我进行修复时,我得到了更多“在编译时不知道大小”的错误

我特别困惑,因为 Rust 的 itertools 库(下面的链接)中的实现具有非常相似的结构,并且不需要指定生命周期、借用、使用框或 dyn 关键字。我很想知道我所做的更改导致 Rust 编译器建议使用借用和/或 Boxes。

error[E0277]: the size for values of type `(dyn Iterator<Item = i8> + 'static)` cannot be kNown at compilation time
  --> src/main.rs:15:8
   |
15 |     a: dyn Iterator<Item=i8>,|        ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size kNown at compile-time
   |
   = help: the trait `Sized` is not implemented for `(dyn Iterator<Item = i8> + 'static)`
   = note: only the last field of a struct may have a dynamically sized type
   = help: change the field's type to have a statically kNown size
help: borrowed types always have a statically kNown size
   |
15 |     a: &dyn Iterator<Item=i8>,|        ^
help: the `Box` type always has a statically kNown size and allocates its contents in the heap
   |
15 |     a: Box<dyn Iterator<Item=i8>>,|        ^^^^                     ^

error[E0277]: the size for values of type `(dyn IntoIterator<Item = i8,IntoIter = (dyn Iterator<Item = i8> + 'static)> + 'static)` cannot be kNown at compilation time
  --> src/main.rs:17:8
   |
17 |     b: dyn IntoIterator<Item=i8,|        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size kNown at compile-time
   |
   = help: the trait `Sized` is not implemented for `(dyn IntoIterator<Item = i8,IntoIter = (dyn Iterator<Item = i8> + 'static)> + 'static)`
   = note: only the last field of a struct may have a dynamically sized type
   = help: change the field's type to have a statically kNown size
help: borrowed types always have a statically kNown size
   |
17 |     b: &dyn IntoIterator<Item=i8,|        ^
help: the `Box` type always has a statically kNown size and allocates its contents in the heap
   |
17 |     b: Box<dyn IntoIterator<Item=i8,IntoIter=dyn Iterator<Item=i8>>>,|        ^^^^                                                         ^

error: aborting due to 2 prevIoUs errors

[1] https://nozaq.github.io/shogi-rs/itertools/trait.Itertools.html#method.cartesian_product 处的文档和 https://github.com/rust-itertools/itertools/blob/master/src/adaptors/mod.rs#L286 处的代码

解决方法

您不仅更改了项目类型,还删除了通用迭代器。在 itertools 板条箱中,有:

pub struct Product<I,J>
    where I: Iterator
{
    a: I,…

意味着 a 是一个迭代器,其确切类型将由用户指定(但仍在编译时)。

您已删除通用 I 参数,而是编写了:

pub struct Product
{
    a: dyn Iterator<Item=i8>,…

如果有效,则意味着 a 是一个迭代器,其项目类型为 u8 但其确切类型将在运行时指定。因此在编译时编译器无法知道 a 的确切类型,也不知道应该分配多少空间来存储 a 内的 Product

如果您希望笛卡尔积适用于项目为 u8 的任何迭代器,您需要使用额外的约束保留泛型参数 I

pub struct Product<I,J>
    where I: Iterator<Item=u8>
{
    a: I,…

J 中的 impl Iterator 也需要进行类似的更改。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...