问题描述
我是 Rust trait 的新手,所以这可能是由于对 supertrait、dyn
或其他任何东西的误解。我正在尝试在枚举中使用特征对象:
最小的例子(在 Rust playground 上编译失败并出现相关错误)是:
#[derive(copy)]
enum Foo {
A,B(dyn MyTraitWhichIscopy),}
trait MyTraitWhichIscopy: copy {}
错误是:
error[E0204]: the trait `copy` may not be implemented for this type
--> src/lib.rs:1:10
|
1 | #[derive(copy)]
| ^^^^
...
4 | B(dyn MyTraitWhichIscopy),| ---------------------- this field does not implement `copy`
|
= note: this error originates in a derive macro (in Nightly builds,run with -Z macro-backtrace for more info)
error: aborting due to prevIoUs error
For more information about this error,try `rustc --explain E0204`.
调用 rustc --explain E0204
后,我注意到以下情况,这可能是我遇到问题的地方:
The `copy` trait is implemented by default only on primitive types. If your
type only contains primitive types,you'll be able to implement `copy` on it.
Otherwise,it won't be possible.
有没有办法完成我想要做的事情?
解决方法
给定的代码有几个问题。
-
特征
Clone
不是对象安全的,因为方法clone
指的是原始 self 类型,通过dyn
抽象是未知的。您的特征具有超特征Copy
并且Copy
具有超特征Clone
,因此您的特征不是对象安全的,这意味着它不能用作特征对象,这也是称为“dyn
特征”。 -
Trait 对象是
?Sized
这意味着它是一个动态大小的类型(DST,其大小在编译时未知)不能用作枚举字段,因为它也使枚举类型 {{ 1}}。在大多数情况下,DST 只能通过引用持有,实际上拥有时为?Sized
,否则为Box<dyn Trait>
或&dyn Trait
。 -
&mut dyn Trait
需要超级特征Copy
,这意味着“任何实现Clone
的类型都必须实现Copy
”。因此,当我们希望我们的自定义类型实现Clone
时,我们应该先实现Copy
。
结论:无法通过 trait 对象来约束一个类型来实现 Clone
或 Copy
,你必须使用一个 Clone
来保存你的 trait 对象,并手动使用一个定义克隆而不是标准的克隆特征并为装箱的特征对象实现克隆:
Box
,
您可以使用由您的特征绑定的泛型类型。另请注意,您还需要 Clone
才能拥有 Copy
:
#[derive(Clone,Copy)]
enum Foo<T: MyTraitWhichIsCopy> {
A,B(T),}
trait MyTraitWhichIsCopy: Copy {}