Multiple bounds for references

Hello,
I have a type that requires a rather long set of bounds. As such, I have created an empty trait that recalls all the used bounds. I then use the trat anywhere I need those bounds.

The problem now is that I need some bounds on the reference type of the trait.

Here is a code that exemplifies the situation. I want function func working without the for<'a> ... bounds. Is that possible somehow?

use num::{Zero, Signed, Num};
use std::ops::{Add, AddAssign, Div, Mul, Sub, SubAssign};


trait Elem: // Make sure R::Elem is Self
    Zero
    + Clone
    + Signed
    + Add<Self, Output = Self>
    + AddAssign
    + Sub<Self, Output = Self>
    + SubAssign
    + Mul<Self, Output = Self>
    + Div<Self, Output = Self>
    + Num
    + Sync
    + Send
    + Sized
    where
        for<'a> &'a Self: Add<&'a Self, Output = Self>
            + Sub<&'a Self, Output = Self>
            + Mul<&'a Self, Output = Self>
            + Div<&'a Self, Output = Self>

{
}

fn func<R>(a: R) 
where
    R: Elem + std::fmt::Debug,
    // ==========>>> uncommenting the next lines solves the errors! <<<===========
    // for<'a> &'a R: Add<&'a R, Output = R>
    //    + Sub<&'a R, Output = R>
    //    + Mul<&'a R, Output = R>
    //    + Div<&'a R, Output = R>,

{
    println!("{:?}", a);
}

impl Elem for i32 {}

fn main() 
{
   func(5);
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error[E0277]: cannot add `&'a R` to `&'a R`
  --> src/main.rs:30:8
   |
30 |     R: Elem + std::fmt::Debug,
   |        ^^^^ no implementation for `&'a R + &'a R`
   |
   = help: the trait `for<'a> Add` is not implemented for `&'a R`
note: required by a bound in `Elem`
  --> src/main.rs:20:27
   |
5  | trait Elem: // Make sure R::Elem is Self
   |       ---- required by a bound in this trait
...
20 |         for<'a> &'a Self: Add<&'a Self, Output = Self>
   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Elem`
help: consider extending the `where` clause, but there might be an alternative better way to express this requirement
   |
30 |     R: Elem + std::fmt::Debug, for<'a> &'a R: Add
   |                              ~~~~~~~~~~~~~~~~~~~~

error[E0277]: cannot subtract `&'a R` from `&'a R`
  --> src/main.rs:30:8
   |
30 |     R: Elem + std::fmt::Debug,
   |        ^^^^ no implementation for `&'a R - &'a R`
   |
   = help: the trait `for<'a> Sub` is not implemented for `&'a R`
note: required by a bound in `Elem`
  --> src/main.rs:21:15
   |
5  | trait Elem: // Make sure R::Elem is Self
   |       ---- required by a bound in this trait
...
21 |             + Sub<&'a Self, Output = Self>
   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Elem`
help: consider extending the `where` clause, but there might be an alternative better way to express this requirement
   |
30 |     R: Elem + std::fmt::Debug, for<'a> &'a R: Sub
   |                              ~~~~~~~~~~~~~~~~~~~~

error[E0277]: cannot multiply `&'a R` by `&'a R`
  --> src/main.rs:30:8
   |
30 |     R: Elem + std::fmt::Debug,
   |        ^^^^ no implementation for `&'a R * &'a R`
   |
   = help: the trait `for<'a> Mul` is not implemented for `&'a R`
note: required by a bound in `Elem`
  --> src/main.rs:22:15
   |
5  | trait Elem: // Make sure R::Elem is Self
   |       ---- required by a bound in this trait
...
22 |             + Mul<&'a Self, Output = Self>
   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Elem`
help: consider extending the `where` clause, but there might be an alternative better way to express this requirement
   |
30 |     R: Elem + std::fmt::Debug, for<'a> &'a R: Mul
   |                              ~~~~~~~~~~~~~~~~~~~~

error[E0277]: cannot divide `&'a R` by `&'a R`
  --> src/main.rs:30:8
   |
30 |     R: Elem + std::fmt::Debug,
   |        ^^^^ no implementation for `&'a R / &'a R`
   |
   = help: the trait `for<'a> Div` is not implemented for `&'a R`
note: required by a bound in `Elem`
  --> src/main.rs:23:15
   |
5  | trait Elem: // Make sure R::Elem is Self
   |       ---- required by a bound in this trait
...
23 |             + Div<&'a Self, Output = Self>
   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Elem`
help: consider extending the `where` clause, but there might be an alternative better way to express this requirement
   |
30 |     R: Elem + std::fmt::Debug, for<'a> &'a R: Div
   |                              ~~~~~~~~~~~~~~~~~~~~

For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` (bin "playground") due to 4 previous errors

Currently you can't, traits only imply bounds on the type that implements them. See where clauses are only elaborated for supertraits, and not other things · Issue #20671 · rust-lang/rust · GitHub

As a workaround, if you're using the nightly toolchain you can use a trait alias instead.

2 Likes