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>
?
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.