无法为实现我拥有的特征的所有类型实现我不拥有的特征

Can't implement a trait I don't own for all types that implement a trait I do own

pub trait AllValues {
    fn all_values() -> Vec<Self> where Self: std::marker::Sized;
}

use rand::Rand;
use rand::Rng;
impl<T: AllValues + Sized> Rand for T {
    fn rand<R: Rng, T>(rng: &mut R) -> T {
        let values = T::all_values();

        let len = values.len();

        if len == 0 {
            panic!("Cannot pick a random value because T::all_values() returned an empty vector!")
        } else {
            let i = rng.gen_range(0, len);

            values[i]
        }
    }
}

前面的代码产生以下编译时错误:

error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g. `MyStruct<T>`); only traits defined in the current crate can be implemented for a type parameter
   --> src/lib.rs:137:1
    |
137 | impl<T: AllValues + Sized> Rand for T {
    | ^

根据提到的实施特征的限制 here 我应该能够为 AllValues 实施 Rand 因为 AllValues 是在我的包中定义的。 coherence/orphan impl 规则实际上允许这样做吗?如果是这样,对于实施 AllValues 的事物实施 Rand 的正确方法是什么?

I should be able to implement Rand for AllValues since AllValues is defined in my crate.

不,您只能为您未定义的类型实现您自己的特征 AllValues。您无法从逻辑上跳转到实现您也未定义的不相关特征。

有两个注意事项要记住:

  • 如果您的特征是 public(它基于您提供的代码),您不是唯一可以实现该特征的人。您的箱子的消费者可能能够为他们自己的类型实现它,他们也可能决定实现 Rand!
  • rand crate 可能决定在未来某个时间 T 实施 Rand

What is the right way to implement Rand for things that implement AllValues?

我不相信有。我只是介绍一个包装器类型,它包含一个值或对实现您的特征的值的引用,并为此实现 Rand

另请参阅:

  • How do I implement a trait I don't own for a type I don't own?

我现在明白我的解释错误在哪里了。引用自 the traits section of the book:

There’s one more restriction on implementing traits: either the trait or the type you’re implementing it for must be defined by you. Or more precisely, one of them must be defined in the same crate as the impl you're writing.

(强调已添加。)

因为我试图实现一个特性,所以我一定把它读作 "either the trait or the trait you’re implementing it for"。 This discussion about an eventually implemented rfc 特别提到了一个与我提出的案例类似的案例:impl<T: Copy> Clone for T 是不允许的。

按照其他地方的建议创建包装器类型是解决此问题的一种方法。假设类型实现的所有权允许,按照建议 为每个具体实例显式实现特征(可选地用宏压缩代码)是另一个。