Operator overloading: lifetime and return type

What's the difference between these four Add methods (matrix operator overloading) ?Do they all return Matrix?
1.impl<'a, T: ops::Add<Output = T> + Copy> ops::Add for &'a Matrix
type Output = Matrix;

  1. impl<'a, T: ops::Add<Output = T> + Copy> ops::Add<Matrix> for &'a Matrix
    type Output = Matrix;

3.impl<T: ops::Add<Output = T> + Copy> ops::Add for Matrix
type Output = Self;

4.impl<'a, T: ops::Add<Output = T> + Copy> ops::Add<&'a Self> for Matrix
type Output = Self;

This looks like a homework problem from a UC Davis class. :wink: Here are some relevant sections of the Rust book that cover what the code is doing: