无法为所有实现我拥有的 trait 的类型实现我不拥有的 trait。

3
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 {
    | ^

根据这里提到的实现特质的限制,我应该能够为AllValues实现Rand,因为AllValues在我的crate中定义。这是否符合一致性/孤立impl规则?如果是,那么为实现AllValues的内容应该采取什么正确的方法呢?

我认为在Rand被定义的地方,这个实例必须被定义。 - undefined
2个回答

4
我应该能够为我的板条箱中定义的AllValues实现Rand。但是,你只能为你没有定义的类型实现自己的特征AllValues。你不能跳跃逻辑来实现另一个无关的特征Rand,因为如果你的特征是公共的(根据你提供的代码是这样的),消费者可能会实现它们自己的类型,他们可能也会决定实现Rand!并且rand箱子将来可能会为T实现Rand
实现AllValues的事物应该如何实现Rand呢?我认为没有正确的方法。我只会介绍一个包装类型,其保存一个值或一个对实现你特征的值的引用,并为其实现Rand
参见:如何为我不拥有的类型实现我不拥有的特征?

1
我现在明白了我的解释错误在哪里。引用自书中的特征部分

实现特征的另一个限制是:你要么定义特征,要么定义类型,其中之一必须由你定义。更准确地说,其中之一必须在与你编写impl的crate中定义。

(强调添加)
由于我试图实现一个特征,我肯定将其解读为“要么特征,要么你正在实现它的特征”。这篇关于最终实现的rfc的讨论特别提到了类似我提出的情况:impl<T: Copy> Clone for T 不被允许。
创建一个包装类型是解决这个问题的一种方法。假设拥有类型实现的所有权,为每个具体实例显式实现特质(可以使用宏压缩代码),如此处建议的那样,也是另一种方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接