In mathematics, a field is a set on which addition, subtraction, multiplication and division are defined. I want to create a trait to define this for certain data types:
use std::ops::{Add, Div, Mul, Sub};
pub trait FieldOps<T>:
Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Div<Output = T>
{}
Now I don't just want to allow these operations when they consume the variable but also by reference so I added the following to expand the trait:
impl<'a, T: 'a> FieldOps<T> for &'a T where
&'a T: Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Div<Output = T>
{}
Thus my understanding at this point is that if FieldOps
can be implemented on a type then it is capable of doing things like T+T->T
, &T+&T->T
etc. Because these operations must have been defined in order for T to allow the implementation of FieldOps
.
However if I now try to create a simple function such as the following:
fn add<T>(x: &T, y: &T) -> T
where T: FieldOps<T>
{ x + y }
Then I will receive the compiler error:
16 | { x + y }
| - ^ - &T
| |
| &T
|
help: consider extending the `where` clause, but there might be an alternative better way to express this requirement
|
15 | where T: FieldOps<T>, &T: Add<&T, Output = T>
| +++++++++++++++++++++++++
What do I not understand here?
If I instead use:
fn add<T>(x: &T, y: &T) -> T
where for<'a> &'a T: FieldOps<T>,
{ x + y }
then it will compile but I would have thought the implementation of the trait covers this directly?