GeekLink
GeekLink

Reputation: 13

Trying to figure out why MulAssign is considered not implemented

I'm quite new to rust and to familiarize my self with it I'm trying to implement my own matrix structs.

An other user made me realize that maybe I did not have enough info, so heres a minimum viable code that gives me the error. https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=0dcd5a8c2ebdecb80867addfe7d38ccc

MathData is a trait implemented by f32 and f64 to limit the generic to only these two.

pub trait MatData<T> {}
impl MatData<f64> for f64 {}
impl MatData<f32> for f32 {}

The matrix Struct and Implementation:

pub struct Mat4<T: MatData<T>> {
    data: [T; 16],
}

impl<T: MatData<T>> Index<usize> for Mat4<T> {
    type Output = T;
    fn index(&self, i: usize) -> &T {
        &self.data[i]
    }
}

impl<T: MatData<T>> IndexMut<usize> for Mat4<T> {
    fn index_mut(&mut self, i: usize) -> &mut T {
        &mut self.data[i]
    }
}

impl<T> MulAssign for Mat4<T>
where
    T: MatData<T> + Mul + Add + Mul<Output = T> + Add<Output = T> + Copy,
{
    fn mul_assign(&mut self, rhs: Self) {
        self[0] = self[0] * rhs[0] + self[1] * rhs[4] + self[2] * rhs[8] + self[3] * rhs[12];
        self[1] = self[0] * rhs[1] + self[1] * rhs[5] + self[2] * rhs[9] + self[3] * rhs[13];
        self[2] = self[0] * rhs[2] + self[1] * rhs[6] + self[2] * rhs[10] + self[3] * rhs[14];
        self[3] = self[0] * rhs[3] + self[1] * rhs[7] + self[2] * rhs[11] + self[3] * rhs[15];

        self[4] = self[4] * rhs[0] + self[5] * rhs[4] + self[6] * rhs[8] + self[7] * rhs[12];
        self[5] = self[4] * rhs[1] + self[5] * rhs[5] + self[6] * rhs[9] + self[7] * rhs[13];
        self[6] = self[4] * rhs[2] + self[5] * rhs[6] + self[6] * rhs[10] + self[7] * rhs[14];
        self[7] = self[4] * rhs[3] + self[5] * rhs[7] + self[6] * rhs[11] + self[7] * rhs[15];

        self[8] = self[8] * rhs[0] + self[9] * rhs[4] + self[10] * rhs[8] + self[11] * rhs[12];
        self[9] = self[8] * rhs[1] + self[9] * rhs[5] + self[10] * rhs[9] + self[11] * rhs[13];
        self[10] = self[8] * rhs[2] + self[9] * rhs[6] + self[10] * rhs[10] + self[11] * rhs[14];
        self[11] = self[8] * rhs[3] + self[9] * rhs[7] + self[10] * rhs[11] + self[11] * rhs[15];

        self[12] = self[12] * rhs[0] + self[13] * rhs[4] + self[14] * rhs[8] + self[15] * rhs[12];
        self[13] = self[12] * rhs[1] + self[13] * rhs[5] + self[14] * rhs[9] + self[15] * rhs[13];
        self[14] = self[12] * rhs[2] + self[13] * rhs[6] + self[14] * rhs[10] + self[15] * rhs[14];
        self[15] = self[12] * rhs[3] + self[13] * rhs[7] + self[14] * rhs[11] + self[15] * rhs[15];
    }
}

When using it like so: mat_a *= mat_b; I get this from the compiler:

binary assignment operation *= cannot be applied to type matrix::Mat4<T> the trait std::ops::MulAssign is not implemented for matrix::Mat4<T>"

Upvotes: 1

Views: 310

Answers (1)

&#214;mer Erden
&#214;mer Erden

Reputation: 8793

This happens because your MulAssign implementation:

impl<T> MulAssign for Mat4<T>
where
    T: MatData<T> + Mul + Add + Mul<Output = T> + Add<Output = T> + Copy,

is not general enough as Transform implementation which is:

impl<T> Transform<T>
where
    T: MatData<T> + Add + Mul + Copy,

The difference is MulAssign implementation explicitly states the associated types of Mul and Add as Output = T, this makes the MulAssign impl less general than Transform impl and as a result you cannot use MulAssign behavior in Transform

To use it you either need to make MulAssign more general(according to your implementation it is not possible) or(then) you need to make Transform less general like :

impl<T> Transform<T>
where
    T: MatData<T> +  Mul<Output = T> + Add<Output = T> + Copy,
{

Upvotes: 0

Related Questions