Rust编译器正在尝试检查与我的代码无关的类型上的trait实现时,遇到trait计算递归限制

sq1bmfud  于 2023-02-12  发布在  其他
关注(0)|答案(1)|浏览(123)

我构造了下面的例子,它至少是近似最小的。

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);
}

尝试编译此代码会产生以下错误消息:

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

我正在使用夜间构建。
这个例子非常接近我想写的一些真实的代码,并且在功能上与一些给我带来麻烦的测试代码相同。奇怪的是,如果你注解掉Mul的第二个实现,它编译起来没有问题。我不能在我的真实代码中这样做。
究竟为什么rustc要查看Wrap <Simd <_, _>>是否实现了ScalarMulCore?我从来没有要求过这种类型。即使我要求了,为什么这会导致rustc达到递归极限?还有,为什么只有当我试图为&Wrap <T>另外实现Mul时,rustc才这样做?

相关问题