请考虑以下代码:

type ThingIter = dyn Iterator<Item = u64>;

trait Foo {
    type ThingIter: Iterator<Item = u64>;
}

enum Bar<T: Foo> {
    A(T::ThingIter),
    B(ThingIter),
}

使用Rust-1.68.2进行编译时,enum arm A编译得很好(即,如果我注释掉B,它就会编译),但enum arm B不能--我得到一个错误,表明ThingIter没有在编译时可以知道的大小.

为什么会有这种不同呢?T::ThingIter的大小在编译时也是未知的(它可以是任意大小容器的迭代器).此外,除了将其放入Box或引用之外,我还可以做些什么来使外部type的行为类似于内部type(即,我可以将其放入枚举中而不会出现问题)?

推荐答案

T::ThingIter的大小在编译时也是未知的(它可以是任意大小容器的迭代器).

T::ThingIter确实有一个已知的大小,因为有一个implicit + Sized bound.如果您还想接受未调整大小的类型,则必须明确 Select 不使用它.如果您放松该约束,则它也无法编译:

trait Foo {
    type ThingIter: Iterator<Item = u64> + ?Sized;
}

结果:

error[E0277]: the size for values of type `<T as Foo>::ThingIter` cannot be known at compilation time
 --> src/lib.rs:8:7
  |
8 |     A(T::ThingIter),
  |       ^^^^^^^^^^^^ doesn't have a size known at compile-time

此外,除了将其放入Box或引用之外,我可以做些什么来使外部type的行为类似于内部type(即,我可以将其放入enum而不会出现问题)?

这些都是常见的解决方案.枚举变体不允许包含动态调整大小的字段.

如果迭代器在其他地方拥有,则&借入有效;否则,像BoxRcArc这样的拥有指针是合理的.

Rust相关问答推荐

将此字符串转换为由空格字符分隔的空格

为什么我不能从带有字符串的 struct 的引用迭代器中收集VEC<;&;str&>?

有没有办法指定只在Rust的测试中有效的断言?

自定义结果枚举如何支持`?`/`FromResidual`?

Rust&;Tokio:如何处理更多的信号,而不仅仅是SIGINT,即SIGQUE?

异步函数返回的future 生存期

如何将实现多个特征的 struct 传递给接受这些特征为&;mut?

如何以与平台无关的方式将OsString转换为utf-8编码的字符串?

如何在 Rust 中打印 let-else 语句中的错误?

decltype、dyn、impl traits,重构时如何声明函数的返回类型

使用 `clap` 在 Rust CLI 工具中设置布尔标志

&str 的编译时拆分是否可能?

为什么在 macOS / iOS 上切换 WiFi 网络时 reqwest 响应会挂起?

如何在 Rust Polars 中可靠地连接 LazyFrames

从 Cranelift 发出 ASM

有没有办法阻止 rust-analyzer 使非活动代码变暗?

有没有办法隐藏类型定义?

在 Rust 中组合特征的不同方法是否等效?

有没有比多个 push_str() 调用更好的方法将字符串链接在一起?

这个 match 语句的默认值应该是什么,还有一种方法可以解开 Some case (chess in rust)