2

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 of Mul, the stack trace becomes non-deterministic. Sometimes, it will refer to traits that aren't even imported, like Complex or Ratio where _ appears.
  • It doesn't matter what the constraints are for the the generic parameter E. I can create a new trait instead of using Float 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.?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
drhagen
  • 8,331
  • 8
  • 53
  • 82
  • This is similar to https://stackoverflow.com/questions/39397157/overflow-evaluating-the-requirement-but-that-kind-of-recursion-should-not-happ. – Francis Gagné Jun 03 '17 at 18:49

0 Answers0