Hi,
in my toy project I'm experimenting with an abstraction over different bignum implementations. These typically implement arithmetic operations on references to avoid unnecessary clones. Unfortunately my attempts seem to lead to infinite recursions in the type system. Here is an example for such an attempt:
trait BigNum
where
for<'a1, 'a2> &'a1 Self: std::ops::Add<&'a2 Self, Output = Self>,
{
}
struct BigNumWrapper<T> {
x: T,
}
impl<'a1, 'a2, T> std::ops::Add<&'a2 BigNumWrapper<T>> for &'a1 BigNumWrapper<T>
where
&'a1 T: std::ops::Add<&'a2 T, Output = T>,
{
type Output = BigNumWrapper<T>;
fn add(self, other: &'a2 BigNumWrapper<T>) -> Self::Output {
BigNumWrapper {
x: &self.x + &other.x,
}
}
}
impl<T: BigNum> BigNum for BigNumWrapper<T> {}
This leads to the following error:
error[E0275]: overflow evaluating the requirement `<&_ as std::ops::Add<&_>>::Output`
Note that this does not seem to be caused by the obvious recursion in the last impl. Introducing a copy BigNum2
of BigNum
and replacing the constraint in the last impl by T: BigNum2
gives the same error.
Also the analogous code using values instead of references compiles just fine: Playground
I'd be very grateful if somebody could shed some light on what the problem is here.
Update: Even though this concrete error can be fixed by repeating the constraint on &'a1 Self
(see the discussion below), the same infinite recursion keeps popping up when actually trying to use the BigNumWrapper
, in particular in the context of type inference. I therefore did not find this approach viable. Instead I am now implementing the arithmetic operators via a macro for the concrete types T
that I want to wrap. The code can be found here in case anyone is interested.