迭代器的 Rust "doesn't have a size known at compile-time" 错误?
Rust "doesn't have a size known at compile-time" error for iterators?
我正在重构 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 库(下面 link)中的实现具有非常相似的结构,不需要指定生命周期、借用、使用 Boxes 或 dyn 关键字。我很想知道我所做的更改导致 Rust 编译器建议使用借用 and/or 框。
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, IntoIter=dyn Iterator<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, IntoIter=dyn Iterator<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 and code at 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
的确切类型,也不知道应该分配多少 space 来存储 Product
.
中的 a
如果您希望您的笛卡尔积适用于任何项目为 u8
的迭代器,您需要使用额外的约束来保留通用参数 I
:
pub struct Product<I, J>
where I: Iterator<Item=u8>
{
a: I,
…
impl Iterator
中的 J
也需要进行类似的更改。
我正在重构 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 库(下面 link)中的实现具有非常相似的结构,不需要指定生命周期、借用、使用 Boxes 或 dyn 关键字。我很想知道我所做的更改导致 Rust 编译器建议使用借用 and/or 框。
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, IntoIter=dyn Iterator<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, IntoIter=dyn Iterator<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 and code at 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
的确切类型,也不知道应该分配多少 space 来存储 Product
.
a
如果您希望您的笛卡尔积适用于任何项目为 u8
的迭代器,您需要使用额外的约束来保留通用参数 I
:
pub struct Product<I, J>
where I: Iterator<Item=u8>
{
a: I,
…
impl Iterator
中的 J
也需要进行类似的更改。