超级特征与其自身作为通用参数绑定的Rust特征

时间:2019-11-09 16:50:15

标签: rust

在使用特征层次结构时,我遇到了以下问题:特征(用作特征对象)应定义一个返回其自身类型的函数。当然,Self不能使用,因为每个子类型会有所不同。相反,特征应该返回特征对象的类型,例如:

trait MySpecialTrait {
    fn clone(&self) -> Box<dyn MySpecialTrait>;
}

到目前为止,这可行。但是现在我想在其自己的通用特征中提取此功能,以便能够编写仅依赖于特征属性的通用代码,如下所示:

trait Cloneable<Output: ?Sized> {
    fn clone(&self) -> Box<Output>;
}

trait MySpecialTrait: Cloneable<dyn MySpecialTrait> {
    fn something(&self);
}

fn clone_all<T>(data: &Vec<Box<T>>) -> Vec<Box<T>> 
    where T: ?Sized + Cloneable<T>
{
    data.iter().map(|x|x.clone()).collect()
}

但是此代码会产生以下错误:

error[E0391]: cycle detected when computing the supertraits of `MySpecialTrait`
  --> src\main.rs:28:1
   |
28 | trait MySpecialTrait: Cloneable<dyn MySpecialTrait> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: ...which again requires computing the supertraits of `MySpecialTrait`, completing the cycle
note: cycle used when collecting item types in top-level module
  --> src\main.rs:28:1
   |
28 | trait MySpecialTrait: Cloneable<dyn MySpecialTrait> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

使用类似的关联类型不会更改任何内容:

trait Cloneable {
    type Output;
    fn clone(&self) -> Box<Self::Output>;
}

trait MySpecialTrait: Cloneable<Output = dyn MySpecialTrait> {
    fn something(&self);
}

有人可以向我解释为什么会有周期吗?我了解在一般情况下,trait A: B的{​​{1}}的超性才能计算出B的超性,所以

A

无法工作。但是在这种情况下,trait A: B {} trait B: A {} 仅在通用类型参数中被引用,那么为什么需要计算MySpecialTrait的超特性?

除此之外,是否有解决此问题的方法?

修改 我不希望Cloneable<dyn MySpecialTrait>仅适用于clone_all的所有具体子类型,也不希望适用于所有特征类型,例如我想用Cloneable<T>类型的参数调用clone_all

0 个答案:

没有答案