derive_more icon indicating copy to clipboard operation
derive_more copied to clipboard

Sum/Product traits don't forward &Self properly

Open obscurans opened this issue 1 year ago • 1 comments
trafficstars

rustc 1.76.0, derive_more 1.0.0-beta.6

This is a very common use case for derived Sum and Product:

#[derive(From, Add, Sum, Mul, Product)
#[mul(forward)]
struct Foo(i32);

let x: Vec<Foo> = vec![1.into(), 2.into(), 3.into()];
let y: Foo = x.iter().sum();
let z: Foo = x.iter().product();

which isn't derived:

error[E0277]: a value of type `Foo` cannot be made by summing an iterator over elements of type `&Foo`
   |
   | let y: &Foo = x.iter().sum();
   |                        ^^^ value of type `&Foo` cannot be made by summing a `std::iter::Iterator<Item=&Foo>`
   |
   = help: the trait `derive_more::Sum<&Foo>` is not implemented for `&Foo`
   = help: the trait `derive_more::Sum` is implemented for `Foo`
note: the method call chain might not have had the expected associated types
   |
   | let x: Vec<Foo> = vec![1.into(), 2.into(), 3.into()];
   |                   ---------------------------------- this expression has type `Vec<Foo>`
   | let y: &Foo = x.iter().sum();
   |                 ^^^^^^ `Iterator::Item` is `&Foo` here
note: required by a bound in `std::iter::Iterator::sum`
  --> /rustc/07dca489ac2d933c78d3c5158e3f43beefeb02ce/library/core/src/iter/traits/iterator.rs:3630:5

error[E0277]: a value of type `Foo` cannot be made by multiplying all elements of type `&Foo` from an iterator
   |
   |     let z: Foo = x.iter().product();
   |                           ^^^^^^^ value of type `Foo` cannot be made by multiplying all elements from a `std::iter::Iterator<Item=&Foo>`
   |
   = help: the trait `derive_more::Product<&Foo>` is not implemented for `Foo`
   = help: the trait `derive_more::Product` is implemented for `Foo`
   = help: for that trait implementation, expected `Foo`, found `&Foo`
note: the method call chain might not have had the expected associated types
   |
   |     let x: Vec<Foo> = vec![1.into(), 2.into(), 3.into()];
   |                       ---------------------------------- this expression has type `Vec<Foo>`
   |     let y: Foo = x.iter().sum();
   |     let z: Foo = x.iter().product();
   |                    ^^^^^^ `Iterator::Item` is `&Foo` here
note: required by a bound in `std::iter::Iterator::product`
  --> /rustc/07dca489ac2d933c78d3c5158e3f43beefeb02ce/library/core/src/iter/traits/iterator.rs:3663:5

Note that std::iter::Sum gives impl<'a> Sum<&'a NUMERIC> for NUMERIC for a bunch of types.

obscurans avatar Mar 31 '24 13:03 obscurans