Search code examples
rusttraits

Rust compiler is hitting trait evaluation recursion limit trying to check for trait implementations on types unrelated to my code


I have constructed the following example. It is at least approximately minimal.

use std::ops::Mul;

trait Muls<Rhs>:
    Mul<Rhs, Output = <Self as Muls<Rhs>>::Output>
    + for<'a> Mul<&'a Rhs, Output = <Self as Muls<Rhs>>::Output>
{
    type Output;
}

impl<T, R, O> Muls<R> for T
where
    T: Mul<R, Output = O>,
    T: for<'a> Mul<&'a R, Output = O>,
{
    type Output = O;
}

trait ScalarMulCore {
    type Scalar;

    fn scalar_mul(&self, rhs: &Self::Scalar) -> Self;

    fn scalar_mul_in_place(&mut self, rhs: &Self::Scalar);
}

struct Wrap<T> {
    x: T,
}

impl<T> ScalarMulCore for Wrap<T>
where
    T: Muls<T, Output = T>,
    for<'a> &'a T: Muls<T, Output = T>,
{
    type Scalar = T;

    fn scalar_mul(&self, rhs: &Self::Scalar) -> Self {
        Self { x: (&self.x) * rhs }
    }

    fn scalar_mul_in_place(&mut self, rhs: &Self::Scalar) {
        self.x = (&self.x) * rhs;
    }
}

impl<T> Mul<<Wrap<T> as ScalarMulCore>::Scalar> for Wrap<T>
where
    Wrap<T>: ScalarMulCore,
{
    type Output = Wrap<T>;

    fn mul(mut self, rhs: <Wrap<T> as ScalarMulCore>::Scalar) -> Self::Output {
        <Wrap<T> as ScalarMulCore>::scalar_mul_in_place(&mut self, &rhs);
        self
    }
}

impl<T> Mul<<Wrap<T> as ScalarMulCore>::Scalar> for &Wrap<T>
where
    Wrap<T>: ScalarMulCore,
{
    type Output = Wrap<T>;

    fn mul(self, rhs: <Wrap<T> as ScalarMulCore>::Scalar) -> Self::Output {
        <Wrap<T> as ScalarMulCore>::scalar_mul(self, &rhs)
    }
}

fn main() {
    let a = Wrap::<isize> { x: 2 };
    let b: isize = 3;

    assert_eq!((a * b).x, 6);
}

Trying to compile this produces the following error message:

   Compiling mwe v0.1.0 (/home/zistack/Projects/mwe)
error[E0275]: overflow evaluating the requirement `for<'a> &'a Simd<_, _>: Mul<Simd<_, _>>`
  --> src/main.rs:47:56
   |
47 | impl <T> Mul <<Wrap <T> as ScalarMulCore>::Scalar> for Wrap <T>
   |                                                        ^^^^^^^^
   |
   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`mwe`)
note: required for `&'a Simd<_, _>` to implement `for<'a> Muls<Simd<_, _>>`
  --> src/main.rs:10:16
   |
10 | impl <T, R, O> Muls <R> for T
   |                ^^^^^^^^     ^
11 | where
12 |     T: Mul <R, Output = O>,
   |                ---------- unsatisfied trait bound introduced here
note: required for `Wrap<Simd<_, _>>` to implement `ScalarMulCore`
  --> src/main.rs:29:10
   |
29 | impl <T> ScalarMulCore for Wrap <T>
   |          ^^^^^^^^^^^^^     ^^^^^^^^
...
32 |     for <'a> &'a T: Muls <T, Output = T>
   |                              ---------- unsatisfied trait bound introduced here
   = note: 62 redundant requirements hidden
   = note: required for `Wrap<_>` to implement `ScalarMulCore`

error[E0275]: overflow evaluating the requirement `for<'a> &'a Simd<_, _>: Mul<Simd<_, _>>`
  --> src/main.rs:59:56
   |
59 | impl <T> Mul <<Wrap <T> as ScalarMulCore>::Scalar> for &Wrap <T>
   |                                                        ^^^^^^^^^
   |
   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`mwe`)
note: required for `&'a Simd<_, _>` to implement `for<'a> Muls<Simd<_, _>>`
  --> src/main.rs:10:16
   |
10 | impl <T, R, O> Muls <R> for T
   |                ^^^^^^^^     ^
11 | where
12 |     T: Mul <R, Output = O>,
   |                ---------- unsatisfied trait bound introduced here
note: required for `Wrap<Simd<_, _>>` to implement `ScalarMulCore`
  --> src/main.rs:29:10
   |
29 | impl <T> ScalarMulCore for Wrap <T>
   |          ^^^^^^^^^^^^^     ^^^^^^^^
...
32 |     for <'a> &'a T: Muls <T, Output = T>
   |                              ---------- unsatisfied trait bound introduced here
   = note: 62 redundant requirements hidden
   = note: required for `Wrap<_>` to implement `ScalarMulCore`

For more information about this error, try `rustc --explain E0275`.
error: could not compile `mwe` due to 2 previous errors

I am using the nightly build.

The this example is pretty close to some real code that I want to write, and functionally identical to some test code that has been giving me some trouble. Strangely enough, if you comment out the second implementation of Mul, it compiles without issue. I cannot get away with doing this in my real code.

Why on earth is rustc trying to see if Wrap <Simd <_, _>> implements ScalarMulCore? I never asked for that type. Even if I did, why would that cause rustc to hit the recursion limit? Also, why is rustc only doing this when I attempt to additionally implement Mul for &Wrap <T>?


Solution

  • I know I'm linking to my own comment here, but it would appear that this behavior is a long-standing bug in the rust compiler.