编译器强制我实现trait方法,但是该方法上的`Self` trait限定在我的类型上从未被满足。

11

我有一个特质Foo。如果实现者实现了另一个特质(例如Clone),我想强制实现者定义一个方法。我的想法(Playground):

trait Foo {
    // Note: in my real application, the trait has other methods as well,
    // so I can't simply add `Clone` as super trait
    fn foo(&self) 
    where 
        Self: Clone;
}

struct NoClone;
impl Foo for NoClone {}

不幸的是,这导致了以下问题:

error[E0046]: not all trait items implemented, missing: `foo`
 --> src/lib.rs:8:1
  |
2 | /     fn foo(&self) 
3 | |     where 
4 | |         Self: Clone;
  | |____________________- `foo` from trait
...
8 |   impl Foo for NoClone {}
  |   ^^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation

我不理解这个错误:编译器明显知道 NoClone 没有实现 Clone,那么为什么我需要提供 foo 的定义?特别是,如果我尝试提供一个定义(Playground):
impl Foo for NoClone {
    fn foo(&self) 
    where 
        Self: Clone
    {
        unreachable!()
    }
}

I get the error:

error[E0277]: the trait bound `NoClone: std::clone::Clone` is not satisfied
  --> src/lib.rs:9:5
   |
9  | /     fn foo(&self) 
10 | |     where 
11 | |         Self: Clone
12 | |     {
13 | |         unreachable!()
14 | |     }
   | |_____^ the trait `std::clone::Clone` is not implemented for `NoClone`
   |
   = help: see issue #48214
   = help: add #![feature(trivial_bounds)] to the crate attributes to enable

这样编译器就可以确定。 (FYI:使用#![feature(trivial_bounds)]进行编译,但我不想定义一堆带有unreachable!()作为主体的方法。)

为什么编译器强制要求我提供方法定义?我能否以某种方式解决这个问题?


我认为这种功能会破坏V表。 - Stargateur
@Stargateur 或者只是一个特质不具备对象安全性的另一个条件。 - Peter Hall
1
你可能会觉得这个问题很有趣。 - Tim Diekmann
1个回答

12
所有trait的实现者都需要实现所有没有默认实现的方法。这是trait拥有定义接口的目的。在方法中添加trait边界不会改变这个规则。
这就是语言参考对此主题的说法:
“trait实现必须定义实现的trait声明的所有非默认关联项,可以重新定义实现的trait定义的默认关联项,并且不能定义任何其他项。”
这也意味着,在trait上声明一个Self的trait绑定在方法声明中,与声明超级trait在功能上是等效的,只是该trait只能在声明绑定的方法中使用。
显然的解决方法是为具有对Self有附加要求的方法定义单独的trait:
trait FooExt: Foo + Clone {
    fn foo(&self);
}

现在可以为所有类型实现Foo,并且对于那些Clone的类型,还可以额外实现FooExt
更新:根据评论中的要求进行了更新:有一个GitHub问题讨论是否允许实现具有无法满足的trait限制的方法而不需要方法体,所以至少可以删除{ unimplemented()! }部分。截至2019年4月,这个讨论还没有得出任何结论,甚至没有确定实现不可调用方法的确切语法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接