[英]Conflicting trait implementations even though associated types differ
I'm trying to an create a generic struct which wraps an isize
or an AtomicIsize
, but I am running into an error when I try to implement a trait for both possible implementations of the struct.我正在尝试创建一个通用结构,它包装
isize
或AtomicIsize
,但是当我尝试为结构的两种可能实现实现特征时遇到错误。 I created a minimal example which demonstrates my issue below.我创建了一个最小示例,它在下面演示了我的问题。
use std::sync::atomic::{AtomicIsize, Ordering};
use std::ops::Deref;
use std::marker::PhantomData;
pub trait Counted {
fn inc(&self, value: isize);
}
pub type PlainCounter = isize;
pub type AtomicCounter = AtomicIsize;
pub struct Counter<'a, T: 'a> {
counter: T,
phantom: PhantomData<&'a T>,
}
impl<'a, T> Counter<'a, T>
where T: Deref<Target = PlainCounter>
{
pub fn new(counter: T) -> Self {
Counter {
counter: counter,
phantom: PhantomData,
}
}
}
impl<'a, T> Counted for Counter<'a, T>
where T: Deref<Target = PlainCounter>
{
fn inc(&self, value: isize) {
self.counter += 1;
}
}
impl<'a, T> Counter<'a, T>
where T: Deref<Target = AtomicCounter>
{
pub fn new(counter: T) -> Self {
Counter {
counter: counter,
phantom: PhantomData,
}
}
}
impl<'a, T> Counted for Counter<'a, T>
where T: Deref<Target = AtomicCounter>
{
fn inc(&self, value: isize) {
self.counter.fetch_add(value, Ordering::SeqCst);
}
}
( playground ) ( 操场)
The error I get is that the compiler found conflicting implementations of trait `Counted` for type `Counter<'_, _>`
.我得到的错误是编译器发现
conflicting implementations of trait `Counted` for type `Counter<'_, _>`
。 It seems that the compiler cannot determine that the implementations are for two different types T
, namely T: Deref<Target = PlainCounter>
and T: Deref<Target = AtomicCounter>
.似乎编译器无法确定实现是针对两种不同类型的
T
,即T: Deref<Target = PlainCounter>
和T: Deref<Target = AtomicCounter>
。 Is there perhaps a way to provide additional information to the compiler so it can distinguish between the two cases, or am I on the wrong path entirely?有没有办法向编译器提供附加信息,以便它可以区分这两种情况,还是我完全走错了路?
You can accomplish this pattern by defining a second trait that does the actual work, and is implemented for (Counter<'a, T>, <T as Deref>::Target)
, and have the Counter
trait call out to that implementation.您可以通过定义执行实际工作的第二个特征来完成此模式,并为
(Counter<'a, T>, <T as Deref>::Target)
,并让Counter
特征调用该实现。
I don't think that was very clear, but I think an example can illustrate well.我认为这不是很清楚,但我认为一个例子可以很好地说明。 Using Shepmaster's shorter example for clarity, we would go from this:
为清楚起见,使用 Shepmaster 较短的示例,我们将从以下内容出发:
use std::ops::Deref;
trait Foo {}
impl<T> Foo for T
where T: Deref<Target = u8>
{}
impl<T> Foo for T
where T: Deref<Target = bool>
{}
fn main() {}
to this:对此:
use std::ops::Deref;
trait Foo {}
trait InnerFoo {}
impl<T> Foo for T
where T: Deref,
(T, <T as Deref>::Target): InnerFoo
{}
impl<T> InnerFoo for (T, u8)
{}
impl<T> InnerFoo for (T, bool)
{}
fn main() {}
Unfortunately this is not implemented in the language yet.不幸的是,这还没有在语言中实现。
There's this tracking issue: rust-lang/rust#20400 .有这个跟踪问题: rust-lang/rust#20400 。
An RFC rust-lang/rfcs#1672 was also proposed to solve this problem but was then postponed waiting for Chalk integration which will make it easier to implement.一个 RFC rust-lang/rfcs#1672也被提出来解决这个问题,但后来被推迟,等待Chalk 集成,这将使它更容易实现。
In the meantime, you'll have to use the workaround proposed above .同时,您必须使用上面提出的解决方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.