无法创建默认特征实现

时间:2021-01-03 04:27:15

标签: rust

我正在尝试实现一个矢量数学库,该库可以根据处理器支持的功能集生成函数的 SIMD 优化版本。目前我为每个功能集都有一个结构和一个定义回退结构的特征。我在特征集结构上实现每个操作。我一直无法实现回退机制。我现在所拥有的会产生流动错误。

error[E0119]: conflicting implementations of trait `Add<Vec4, Vec4>` for type `Scalar`:
  --> src/main.rs:41:1
   |
14 | default impl<F: FeatureSet, Lhs, Rhs> Add<Lhs, Rhs> for F where <F as FeatureSet>::Fallback: Add<Lhs, Rhs> {
   | ---------------------------------------------------------------------------------------------------------- first implementation here
...
41 | impl Add<Vec4, Vec4> for Scalar {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Scalar`

有人对如何解决这个问题有任何建议吗?

Playground

示例代码:

#![feature(specialization)]
use std::arch::x86_64 as arch;

trait FeatureSet {
    type Fallback;
}

trait Add<Lhs, Rhs> {
    type Output;
    unsafe fn add(lhs: Lhs, rhs: Rhs) -> Self::Output;
}

// Attempt at implementing fallback to implementation in Fallback type
default impl<F: FeatureSet, Lhs, Rhs> Add<Lhs, Rhs> for F where <F as FeatureSet>::Fallback: Add<Lhs, Rhs> {
    type Output = <<F as FeatureSet>::Fallback as Add<Lhs, Rhs>>::Output;
    unsafe fn add(lhs: Lhs, rhs: Rhs) -> Self::Output {
        <F as FeatureSet>::Fallback::add(lhs, rhs)
    }
}

#[repr(C)]
union Vec4 {
    scalar: std::mem::ManuallyDrop<[f32; 4]>,
    #[allow(unused)]
    simd: std::mem::ManuallyDrop<arch::__m128>,
}

impl std::convert::From<[f32; 4]> for Vec4 {
    fn from(values: [f32; 4]) -> Self {
        Self {
            scalar: std::mem::ManuallyDrop::new(values)
        }
    }
}

struct Scalar;
impl FeatureSet for Scalar {
    type Fallback = ();
}

impl Add<Vec4, Vec4> for Scalar {
    type Output = Vec4;
    unsafe fn add(lhs: Vec4, rhs: Vec4) -> Self::Output {
        let mut r: [f32; 4] = std::mem::MaybeUninit::uninit().assume_init();
        for i in 0 .. 4 {
            r[i] = lhs.scalar[i] + rhs.scalar[i];
        }
        
        r.into()
    }
}

struct Sse;
impl FeatureSet for Sse {
    type Fallback = Scalar;
}

// Should fall back to implementation in FeatureSet::Fallback type when not implemented
impl Add<Vec4, Vec4> for Sse {
    type Output = Vec4;
    #[inline]
    #[target_feature(enable = "sse")]
    unsafe fn add(lhs: Vec4, rhs: Vec4) -> Self::Output {
        let r = arch::_mm_add_ps(*lhs.simd, *rhs.simd);
        Vec4 {
            simd: std::mem::ManuallyDrop::new(r)
        }
    }
}

#[inline(never)]
// This function should be able to be specialized for each feature set for later
// runtime selection
unsafe fn perform_add<F: FeatureSet>(a: Vec4, b: Vec4) -> Vec4 {
    F::add(a, b)
}

fn main() {
    let a = [0.0, 1.0, 2.0, 3.0].into();
    let b = [4.0, 4.0, 5.0, 6.0].into();
    
    unsafe {
        let c = perform_add::<Sse>(a, b);
        println!("{} {} {} {}", c.scalar[0], c.scalar[1], c.scalar[2], c.scalar[3]);
    }
}

0 个答案:

没有答案