How to implement AddAssign for extending ndarray?

I'm struggling to understand how to implement AddAssign, and a few others for a new type based on ndarray. Specifically I'm trying to extend ndarray, with some new traits but having trouble figuring out the right incantation. Here's a minimal version of what I'm seeing.


use std::ops::{AddAssign};
use ndarray::{ Array, Array0, Array1 };

struct Wrap<T: AddAssign<Wrap<T>>>(T);
impl<T:AddAssign<T>> AddAssign<T> for Wrap<T> {
    fn add_assign(&mut self, rhs: Self) {
        self.0 += rhs.0
    }
}



// `derive` implements Clone for Reading<T> when T is Clone.
fn main() {
    let vecEx = Array::from(vec![1.]);
    vecEx += Array::from(vec![1.]);

    let wrapped = Wrap(Array::from(vec![1.]));
    wrapped += Wrap(Array::from(vec![1.]));
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
warning: unused imports: `Array0`, `Array1`
 --> src/main.rs:3:23
  |
3 | use ndarray::{ Array, Array0, Array1 };
  |                       ^^^^^^  ^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

error[E0277]: cannot add-assign `Wrap<T>` to `T`
 --> src/main.rs:6:39
  |
6 | impl<T:AddAssign<T>> AddAssign<T> for Wrap<T> {
  |                                       ^^^^^^^ no implementation for `T += Wrap<T>`
  |
note: required by a bound in `Wrap`
 --> src/main.rs:5:16
  |
5 | struct Wrap<T: AddAssign<Wrap<T>>>(T);
  |                ^^^^^^^^^^^^^^^^^^ required by this bound in `Wrap`
help: consider further restricting this bound
  |
6 | impl<T:AddAssign<T> + std::ops::AddAssign<Wrap<T>>> AddAssign<T> for Wrap<T> {
  |                     ++++++++++++++++++++++++++++++

error[E0277]: cannot add-assign `Wrap<T>` to `T`
 --> src/main.rs:7:19
  |
7 |     fn add_assign(&mut self, rhs: Self) {
  |                   ^^^^^^^^^ no implementation for `T += Wrap<T>`
  |
note: required by a bound in `Wrap`
 --> src/main.rs:5:16
  |
5 | struct Wrap<T: AddAssign<Wrap<T>>>(T);
  |                ^^^^^^^^^^^^^^^^^^ required by this bound in `Wrap`
help: consider further restricting this bound
  |
6 | impl<T:AddAssign<T> + std::ops::AddAssign<Wrap<T>>> AddAssign<T> for Wrap<T> {
  |                     ++++++++++++++++++++++++++++++

For more information about this error, try `rustc --explain E0277`.
warning: `playground` (bin "playground") generated 1 warning
error: could not compile `playground` due to 2 previous errors; 1 warning emitted

It's not clear what you are trying to do. Your type annotations don't make sense. You say that you want to impl AddAssign<T> but on the right-hand side, you take Self (i.e., Wrap<T>), not T.

If you fix that type error, fix the inference error resulting from the use of Array (instead of Array1), and account for the fact that you can only add a &Array1 to an Array1, then you can arrive at one possible working implementation.

I'd like to be able to do something like

Wrap += Wrap

The solution you posted is really close to what I'm after, thanks!

I think
Wrap += &Wrap

Would also work for my use case, will see if I can get it working with that.

I think I got what I was after via

Thanks a bunch @H2CO3