gpt4 book ai didi

generics - "Overflow evaluating the requirement"但这种递归根本不应该发生

转载 作者:行者123 更新时间:2023-11-29 07:48:16 25 4
gpt4 key购买 nike

这是一个冗长的示例,因为我无法进一步减少它。 Rust Playground

use std::marker::PhantomData;
use std::ops::{Add, Sub, Mul, Div};

pub trait Scalar
: Sized + Copy + Add<Self, Output = Self> + Sub<Self, Output = Self> + Mul<Self, Output = Self> + Div<Self, Output = Self>
{}
impl Scalar for u32 {}

pub struct ScalarVal<T>(T) where T: Scalar;

pub trait Pixel: Sized {
type ScalarType: Scalar;
}

#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Gray<BaseTypeP>
where BaseTypeP: Scalar
{
intensity: BaseTypeP,
}

impl<BaseTypeP> Pixel for Gray<BaseTypeP>
where BaseTypeP: Scalar
{
type ScalarType = BaseTypeP;
}

impl<BaseTypeP> Add<Gray<BaseTypeP>> for ScalarVal<BaseTypeP>
where BaseTypeP: Scalar
{
type Output = Gray<BaseTypeP>;
fn add(self, rhs: Gray<BaseTypeP>) -> Gray<BaseTypeP> {
unimplemented!()
}
}

pub struct Image<PixelP>
where PixelP: Pixel
{
_marker: PhantomData<PixelP>,
}

impl<PixelP> Add<Image<PixelP>> for ScalarVal<<PixelP as Pixel>::ScalarType>
where PixelP: Pixel,
ScalarVal<<PixelP as Pixel>::ScalarType>: Add<PixelP, Output = PixelP>
{
type Output = Image<PixelP>;
fn add(self, rhs: Image<PixelP>) -> Image<PixelP> {
unimplemented!()
}
}

fn main() {
let a = Gray::<u32> { intensity: 41 };
let b = ScalarVal(1) + a;
}

有人可以解释为什么我得到 overflow evaluating the requirement <_ as Pixel>::ScalarType在该代码段中?

我很困惑,因为:

  • 如果Add删除第 44 行中的实现,代码可以正常编译。但是根本不应该使用该实现=> main()只使用 Gray而不是 Image
  • 递归似乎嵌套在Image<Image<...>> 中结构,但这根本不应该发生?!
  • 如果第46行改为ScalarVal<<PixelP as Pixel>::ScalarType>: Add它编译得很好——但为什么呢?

一些上下文

这是我要构建的图像处理库的一部分。这个想法是有不同的像素格式(灰色,RGB,拜耳,...)可用于图像。因此你有 Image<Gray>对于灰度图像。不同Pixel实现可以实现不同的运算符,因此您可以使用它们进行计算(例如 gray_a = gray_b + gray_c )。也可以在这些实现中使用标量值来做,例如gray_a = gray_b + ScalarVal(42) .因为我想让 ScalarVal 成为可能作为右手 左手参数,需要有两个实现( impl Add<Gray<...>> for ScalarVal<...>impl Add<ScalarVal<...>> for Gray<...> )。

好的,现在 Image type 应实现所用 Pixel 支持的所有运算符类型。如果可以的话 gray_pixel + Scalar(42)也应该可以做 gray_image + Scalar(42) .

希望这是有道理的。

最佳答案

ScalarVal(1) + a基本上解析为 <ScalarVal(1) as Add>.add(a) , 它寻找 AddScalarVal 上实现.

无论出于何种原因,首先检查这个:

impl<PixelP> Add<Image<PixelP>> for ScalarVal<<PixelP as Pixel>::ScalarType>
where PixelP: Pixel,
ScalarVal<<PixelP as Pixel>::ScalarType>: Add<PixelP, Output = PixelP>

PixelP此时未实例化,所以 PixelP: Pixel无法检查。因此我们得到

ScalarVal<<PixelP as Pixel>::ScalarType>: Add<PixelP, Output = PixelP>

让我们简化一下。自 PixelP现在未知,<PixelP as Pixel>::ScalarType未知。编译器已知的实际信息看起来更像是

impl<T> Add<Image<T>> for ScalarVal<_>
where ScalarVal<_>: Add<T, Output = T>

所以 ScalarVal<_>寻找 Add<T, Output = T> .这意味着我们应该寻找合适的 T .显然这意味着查找 ScalarValAdd impl秒。看同一个,我们得到

impl<T2> Add<Image<T2>> for ScalarVal<_>
where ScalarVal<_>: Add<T2, Output = T2>

这意味着如果这个匹配,T == Image<T2> .

显然然后T2 == Image<T3> , T3 == Image<T4>等等。这会导致溢出和普遍的悲伤。 Rust 永远找不到反证,所以永远不能保证它会走错路。

关于generics - "Overflow evaluating the requirement"但这种递归根本不应该发生,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39397157/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com