即使关联类型不同,也会发生冲突的特征实施

时间:2016-11-03 01:42:02

标签: generics struct types rust

我正在尝试创建一个包含isizeAtomicIsize的通用结构,但是当我尝试为结构的两个可能实现实现特征时遇到错误。我创建了一个最小的例子来演示我的问题。

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

我得到的错误是编译器找到了conflicting implementations of trait `Counted` for type `Counter<'_, _>`。似乎编译器无法确定实现是针对两种不同类型T,即T: Deref<Target = PlainCounter>T: Deref<Target = AtomicCounter>。是否有一种方法可以为编译器提供额外的信息,以便区分这两种情况,或者我是否完全走错路径?

2 个答案:

答案 0 :(得分:4)

您可以通过定义执行实际工作的第二个特征来实现此模式,并为(Counter<'a, T>, <T as Deref>::Target)实施,并且具有Counter特征调用该实现。

我不认为这很清楚,但我认为一个例子可以很好地说明。为了清晰起见,使用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() {}

到此:

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() {}

答案 1 :(得分:2)

不幸的是,该语言尚未实现。

存在以下跟踪问题:rust-lang/rust#2400

还提出了RFC rust-lang/rfcs#1672来解决此问题,但后来推迟了等待Chalk integration的时间,这将使其易于实施。

同时,您必须使用建议的above解决方法。