How to reformulate multiple trait bounds as a single trait?

54 Views Asked by At

I have a working library of mathematical functions. My issue is that many of the functions with generic types have verbose trait bounds. For example:

fn some_operation<T>(a: &T, b: &T) -> T 
where
           T: PartialOrd + Signed + Clone + Zero + One + Sum,
  for<'a> &T: Add<&'a T, Output = T>
            + Sub<&'a T, Output = T>
            + Mul<&'a T, Output = T>
            + Div<&'a T, Output = T>
{
// ops
}

I have tried to declare a generic trait including these in the following way:

pub trait ReferencedFieldOps<T>
where 
   for<'a> &'a T: Add<&'a T, Output = T>
                + Sub<&'a T, Output = T>
                + Mul<&'a T, Output = T>
                + Div<&'a T, Output = T>,
{}

So that I can restate my operation to:

fn some_operation<T>(a: &T, b: &T) -> T 
where T: PartialOrd + Signed + Clone + Zero + One + Sum + ReferencedFieldOps<T>
{ 
//ops
}

But this won't compile. I get many no implementation for &'a T + &'a T or similar for other - * / etc. Even though when this was explicitly typed in the first instance there was no issue. Is this the correct way to do this?

1

There are 1 best solutions below

1
Stargateur On

I don't know a way to do this in stable Rust but, if you want you can try out trait_alias experimental feature:

#![feature(trait_alias)]
use core::ops::*;

struct My {
    val: f64,
}

impl<'a> Add<&'a My> for &'a My {
    type Output = My;
    fn add(self, other: &My) -> My {
        My {
            val: (self.val + other.val),
        }
    }
}

pub trait ReferencedFieldOps<T, U> = where T: Add<T, Output = U>;

fn some_operation<T, U>(a: T, b: T) -> U
where
    (): ReferencedFieldOps<T, U>,
{
    a + b
}

fn main() {
    let a = My { val: 2.0 };
    let b = My { val: 2.5 };
    assert_eq!(some_operation(&a, &b).val, 4.5)
}

Playground