编译器强制我实现特征方法,但我的类型永远不会满足方法上绑定的“Self”特征
Compiler forces me to implement trait method but the `Self` trait bound on method is never satisfied for my type
我有一个特点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!()
}
}
我收到错误:
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
所以编译器肯定知道。 (仅供参考:使用 #![feature(trivial_bounds)]
可以编译,但我不想定义一堆方法 unreachable!()
作为主体。)
为什么编译器强制我提供方法定义?我能以某种方式解决这个问题吗?
特性的所有实现者都需要实现所有没有默认实现的方法。它具有定义的接口是特征的要点。向方法添加特征边界不会改变此规则的任何内容。
这是 language reference 对主题的看法:
A trait implementation must define all non-default associated items declared by the implemented trait, may redefine default associated items defined by the implemented trait, and cannot define any other items.
这也意味着在特征的方法声明中绑定到 Self
的特征在功能上等同于声明一个超特征,除了特征只能在声明绑定的方法中使用。
明显的解决方法是为对 Self
:
有额外要求的方法定义一个单独的特征
trait FooExt: Foo + Clone {
fn foo(&self);
}
您现在可以为所有类型实现 Foo
,此外还可以为 Clone
.
类型实现 FooExt
根据评论中的要求更新:有一个GitHub issue discussing whether it should be allowed to implement methods with unsatisfiable trait bounds without the method body,所以至少{ unimplemted()! }
部分可以删除。截止到 2019 年 4 月,这个讨论还没有得出任何结论,甚至连实现不可调用方法的确切语法也没有定论。
我有一个特点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!()
}
}
我收到错误:
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
所以编译器肯定知道。 (仅供参考:使用 #![feature(trivial_bounds)]
可以编译,但我不想定义一堆方法 unreachable!()
作为主体。)
为什么编译器强制我提供方法定义?我能以某种方式解决这个问题吗?
特性的所有实现者都需要实现所有没有默认实现的方法。它具有定义的接口是特征的要点。向方法添加特征边界不会改变此规则的任何内容。
这是 language reference 对主题的看法:
A trait implementation must define all non-default associated items declared by the implemented trait, may redefine default associated items defined by the implemented trait, and cannot define any other items.
这也意味着在特征的方法声明中绑定到 Self
的特征在功能上等同于声明一个超特征,除了特征只能在声明绑定的方法中使用。
明显的解决方法是为对 Self
:
trait FooExt: Foo + Clone {
fn foo(&self);
}
您现在可以为所有类型实现 Foo
,此外还可以为 Clone
.
FooExt
根据评论中的要求更新:有一个GitHub issue discussing whether it should be allowed to implement methods with unsatisfiable trait bounds without the method body,所以至少{ unimplemted()! }
部分可以删除。截止到 2019 年 4 月,这个讨论还没有得出任何结论,甚至连实现不可调用方法的确切语法也没有定论。