"特征的冲突实施"当试图成为通用的时候

时间:2015-06-15 12:55:30

标签: types rust

背景:我正在使用nalgebra库,我想创建一个代表多元正态分布的结构。 M是矩阵的类型,例如Mat4<f64>

我目前的尝试是这样的:

use std::ops::Mul;
use std::marker::PhantomData;
use nalgebra::*;

#[allow(non_snake_case)]
pub struct Multivar<N, V, M: SquareMat<N, V>> {
    μ: V,
    Σ: M,
    marker: PhantomData<N>
}

impl<N, V, M> Mul<Multivar<N, V, M>> for M {
    type Output = Multivar<N, V, M>;
    fn mul(self, rhs: Multivar<N, V, M>) -> Multivar<N, V, M> {
        Multivar {
            μ: self * rhs.μ,
            Σ: self * rhs.Σ * transpose(&self)
        }
    }
}

然而,编译器抱怨:

error: type parameter `M` 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

error: conflicting implementations for trait `core::ops::Mul`

我不相信这应该是一个错误,因为我定义了我在此模块中定义的结构的实现。我该如何解决这个问题?

1 个答案:

答案 0 :(得分:4)

您的代码存在的问题是,您的代码存在连贯性违规行为,并且很有可能,任何修复代码的行为都会导致新的一致性违规行为。

Rust中的一致性规则有点复杂,但是,它们基于一个原则:您可以实现&#34;您的&#34;任意类型的特征,你可以为&#34;你的&#34;实现任意特征。类型。这听起来很简单,但是当类型参数出现时会变得复杂 - 事实证明,有多种方法可以定义哪些类型是&#34;你的&#34;哪些不是。

在这种特殊情况下,错误在于您直接为类型参数实现外部特征:

impl<N, V, M> Mul<Multivar<N, V, M>> for M

这直接违反了上述原则 - 您无法实现您不拥有的类型所拥有的特征(此类实现称为&#34;孤儿impls&#34;)。这正是您的第一个错误。

第二个错误让我觉得你有比你在这里提供的更多Mul个实现;无论如何,这也是一致性违规。通常,如果您具有适用于特征的两个或更多不同实现的类型集的交集,则会导致此类错误:

use std::fmt;

trait X {}

impl X for i32 {}
impl<T: fmt::Display> X for T {}

此处的实施具有冲突性,因为它们都适用于i32,因为i32实施fmt::Display

事实上,很难说出你想要的东西,所以很难给出令人满意的答案。我试图解释上面这些错误的原因,希望它能帮助你正确编写特征实现。如果您有兴趣,可以在this关于孤儿规则的博文中找到更多信息。