[英]How to implement trait for types implementing another trait without conflicting implementations
I have a broad base trait.我有一个广泛的基础特征。 Some types only care about subset of its functionality, so I added a subtrait requiring user to implement smaller set of functions.
有些类型只关心其功能的子集,所以我添加了一个子特征,要求用户实现更小的功能集。
This code fails:此代码失败:
trait Base<T> {
fn foo(arg: bool);
}
// Ext is a narrowing of Base requiring user to provide alternative, simpler interface for the same functionality
trait Ext<T>: Base<T> {
fn bar();
}
// implement Base<T> for all types implementing Ext<T>
impl<T, E> Base<T> for E
where
E: Ext<T>,
{
fn foo(arg: bool) {
Self::bar();
}
}
struct Data<T>;
// error[E0119]: conflicting implementations of trait `Base<_>` for type `Data<_>`:
impl<T> Base<T> for Data<T> {
fn foo(arg: bool) {}
}
With following error:出现以下错误:
error[E0119]: conflicting implementations of trait `Base<_>` for type `Data<_>`:
--> src/lib.rs:22:1
|
11 | / impl<T, E> Base<T> for E
12 | | where
13 | | E: Ext<T>,
14 | | {
... |
17 | | }
18 | | }
| |_- first implementation here
...
22 | impl<T> Base<T> for Data<T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Data<_>`
|
= note: downstream crates may implement trait `Ext<_>` for type `Data<_>`
Interestingly, it works when I remove generality over T
:有趣的是,当我删除
T
的一般性时,它会起作用:
trait Base {
fn foo(arg: bool);
}
// Ext is a narrowing of Base requiring user to provide alternative, simpler interface for the same functionality
trait Ext: Base {
fn bar();
}
// implement Base for all types implementing Ext
impl<E> Base for E
where
E: Ext,
{
fn foo(arg: bool) {
Self::bar();
}
}
struct Data;
// works just fine
impl Base for Data {
fn foo(arg: bool) {}
}
Some other posts on stackoverflow mentioned similar problems, but they generally have issues with foreign traits (the one from standard library). stackoverflow 上的其他一些帖子提到了类似的问题,但它们通常存在外来特征(来自标准库的特征)的问题。 In my case both trait and type are local, therefore orphan rules should not kick in as far as I understand.
就我而言,特征和类型都是本地的,因此据我所知,孤儿规则不应该生效。
Basically, error mentions that downstream crates may implement trait 'Ext<_>' for type 'Data<_>'
, which isn't true because both Ext
and Data
would be foreign for those crates.基本上,错误提到
downstream crates may implement trait 'Ext<_>' for type 'Data<_>'
,这是不正确的,因为Ext
和Data
对于这些板条箱来说都是外来的。
To summarize, my questions are:总而言之,我的问题是:
T
is not rejected, even though its mostly the same blanket impl?T
的版本不会被拒绝,即使它几乎是相同的一揽子 impl?The reason you're seeing the error is that there is a possible collision between impl Base for E and impl Base for Data您看到错误的原因是 impl Base for E 和 impl Base for Data之间可能存在冲突
these are both generics, so in theory I could create my own struct and implement the trait Base<T>
as well as the trait Ext<T>
.这些都是 generics,所以理论上我可以创建自己的结构并实现特征
Base<T>
以及特征Ext<T>
。 If I do this, your code would create duplicate implementations for Base<T>::foo
since Both impl
blocks are implementing Base<T>
.如果我这样做,您的代码将为
Base<T>::foo
创建重复的实现,因为两个impl
块都在实现Base<T>
。
When you remove the T
from your code it becomes more specific.当您从代码中删除
T
时,它会变得更加具体。 You would implement Base
for E
and Base
for Data
.您将为
E
实现Base
和为Data
实现Base
。 You can see the same error in your own second code example if you add the following如果添加以下内容,您可以在自己的第二个代码示例中看到相同的错误
impl Ext for Data {
fn bar() {}
}
It's the same basic message.这是相同的基本信息。 The only difference is your first example only provides the possibility of a collision whereas the second (with my addition) actually causes the collision.
唯一的区别是你的第一个例子只提供了碰撞的可能性,而第二个(加上我的补充)实际上导致了碰撞。
As for workarounds... Rust traits are not really inheritance so I would say the rusty way to do this would be to have separate traits for each subset of functions you want instead of trying to create a hierarchy of traits.至于解决方法... Rust 特征并不是真正的 inheritance 所以我想说的生锈方法是为您想要的每个函数子集设置单独的特征,而不是尝试创建特征层次结构。
If your program really needs to have the inheritance type traits, then avoid using generics or bound them to concrete types.如果您的程序确实需要具有 inheritance 类型特征,则避免使用 generics 或将它们绑定到具体类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.