繁体   English   中英

尝试通用时,“特征的冲突实施”

[英]“conflicting implementations for trait” when trying to be generic

背景:我正在使用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 (eg `MyStruct<T>`); only traits defined in the current crate can be implemented for a type parameter

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

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

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

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

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

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

这直接违反了上述原则 - 您不能为不属于您的类型实现您不拥有的特征(此类实现称为“孤立impls”)。 这正是您的第一个错误。

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

use std::fmt;

trait X {}

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

这里的实现是冲突的,因为它们都适用于i32因为i32实现了fmt::Display

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM