在枚举中使用 Copy 的超特性时,类型不会实现 Copy 错误
Type does not implement Copy error when using supertrait of Copy in an enum
我是 Rust 特性的新手,所以这可能是由于对超级特性的误解,dyn
或其他任何原因。我正在尝试使用枚举中的特征对象来:
- 对可以在枚举的这个元素中使用的具体类型设置特征限制
- 确保枚举仍然可以派生
Copy
最小示例(无法在 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
才能拥有 Copy
:
#[derive(Clone, Copy)]
enum Foo<T: MyTraitWhichIsCopy> {
A,
B(T),
}
trait MyTraitWhichIsCopy: Copy {}
给定的代码中存在几个问题。
特征 Clone
不是对象安全的,因为方法 clone
引用了原始自身类型,通过 dyn
抽象是未知的。你的trait有一个super traitCopy
,而Copy
有一个super traitClone
,所以你的trait不是object-safe,也就是说不能作为trait对象使用,这也是被称为“dyn
特质”。
Trait 对象是 ?Sized
这意味着它是一个动态大小的类型(DST,其大小在编译时未知)不能用作枚举字段,因为它也使得枚举类型 ?Sized
。在大多数情况下,DST 只能通过引用持有,实际上 Box<dyn Trait>
拥有时,否则 &dyn Trait
或 &mut dyn Trait
.
Copy
需要超级特征 Clone
,这意味着“任何实现 Copy
的类型都必须实现 Clone
”。所以当我们希望我们的自定义类型实现Copy
时,我们应该首先实现Clone
。
结论:无法通过trait对象来约束一个类型实现Copy
或Clone
,必须用一个Box
来持有你的trait对象,并使用手动定义克隆而不是标准克隆特征并为盒装特征对象实现克隆:
trait MyTrait {
fn clone_dyn(&self) -> Box<dyn MyTrait>;
}
#[derive(Clone)]
struct MyImpl;
impl MyTrait for MyImpl {
fn clone_dyn(&self) -> Box<dyn MyTrait> {
Box::new(self.clone())
}
}
impl Clone for Box<dyn MyTrait> {
fn clone(&self) -> Self {
self.clone_dyn()
}
}
#[derive(Clone)]
enum Foo {
A,
B(Box<dyn MyTrait>),
}
我是 Rust 特性的新手,所以这可能是由于对超级特性的误解,dyn
或其他任何原因。我正在尝试使用枚举中的特征对象来:
- 对可以在枚举的这个元素中使用的具体类型设置特征限制
- 确保枚举仍然可以派生
Copy
最小示例(无法在 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
才能拥有 Copy
:
#[derive(Clone, Copy)]
enum Foo<T: MyTraitWhichIsCopy> {
A,
B(T),
}
trait MyTraitWhichIsCopy: Copy {}
给定的代码中存在几个问题。
特征
Clone
不是对象安全的,因为方法clone
引用了原始自身类型,通过dyn
抽象是未知的。你的trait有一个super traitCopy
,而Copy
有一个super traitClone
,所以你的trait不是object-safe,也就是说不能作为trait对象使用,这也是被称为“dyn
特质”。Trait 对象是
?Sized
这意味着它是一个动态大小的类型(DST,其大小在编译时未知)不能用作枚举字段,因为它也使得枚举类型?Sized
。在大多数情况下,DST 只能通过引用持有,实际上Box<dyn Trait>
拥有时,否则&dyn Trait
或&mut dyn Trait
.Copy
需要超级特征Clone
,这意味着“任何实现Copy
的类型都必须实现Clone
”。所以当我们希望我们的自定义类型实现Copy
时,我们应该首先实现Clone
。
结论:无法通过trait对象来约束一个类型实现Copy
或Clone
,必须用一个Box
来持有你的trait对象,并使用手动定义克隆而不是标准克隆特征并为盒装特征对象实现克隆:
trait MyTrait {
fn clone_dyn(&self) -> Box<dyn MyTrait>;
}
#[derive(Clone)]
struct MyImpl;
impl MyTrait for MyImpl {
fn clone_dyn(&self) -> Box<dyn MyTrait> {
Box::new(self.clone())
}
}
impl Clone for Box<dyn MyTrait> {
fn clone(&self) -> Self {
self.clone_dyn()
}
}
#[derive(Clone)]
enum Foo {
A,
B(Box<dyn MyTrait>),
}