I have a generic trait Trait<E: Float>
, a generic struct Struct<E: Float>
for that trait, an implementation of Mul
for the struct, and a generic function that takes a Trait
with Mul
.
extern crate num;
use std::ops::Mul;
use num::traits::Float;
trait Trait<E: Float> {}
struct Struct<E: Float> (E);
impl<E: Float> Trait<E> for Struct<E> {}
impl<'a, 'b, E: Float> Mul<&'b Struct<E>> for &'a Struct<E>
where &'a E: Mul<&'b E, Output=E>
{
type Output = Struct<E>;
fn mul(self, rhs: &'b Struct<E>) -> Self::Output { unimplemented!() }
}
fn multiply<'a, E: Float, T: Trait<E>>(x: &'a T) -> T
where &'a T: Mul<&'a T, Output=T>
{
unimplemented!()
}
fn main() {
let matrix = multiply(&Struct(1.0));
}
There is nothing in here that appears to be recursive. However, the compiler errors by bottoming out the recursion:
error[E0275]: overflow evaluating the requirement `<&_ as std::ops::Mul<&_>>::Output`
--> src\main.rs:29:18
|
29 | let matrix = multiply(&Struct(1.0));
| ^^^^^^^^
|
= help: consider adding a `#![recursion_limit="128"]` attribute to your crate
= note: required because of the requirements on the impl of `std::ops::Mul<&Struct<_>>` for `&Struct<_>`
= note: required because of the requirements on the impl of `std::ops::Mul<&Struct<Struct<_>>>` for `&Struct<Struct<_>>`
= note: required because of the requirements on the impl of `std::ops::Mul<&Struct<Struct<Struct<_>>>>` for `&Struct<Struct<Struct<_>>>`
= note: required because of the requirements on the impl of `std::ops::Mul<&Struct<Struct<Struct<Struct<_>>>>>` for `&Struct<Struct<Struct<Struct<_>>>>`
...
Here are some odd facts I have found while debugging and trying to minimize this example:
- If I add
E: Zero
to the type constraints ofMul
, the stack trace becomes non-deterministic. Sometimes, it will refer to traits that aren't even imported, likeComplex
orRatio
where_
appears. - It doesn't matter what the constraints are for the the generic parameter
E
. I can create a new trait instead of usingFloat
and it does the same thing. - This only happens if the
Mul
is defined for references, not owned values.
What do I need to do to not lead the compiler down absurd types like &Struct<Struct<_>>
, etc.?