微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么装饰器模式适用于拥有的类型,但会导致引用的特征评估溢出E0275?

如何解决为什么装饰器模式适用于拥有的类型,但会导致引用的特征评估溢出E0275?

在 Rust 中试验装饰器设计模式时,我遇到了我认为可能是编译器错误的问题,但我对这门语言太陌生,无法自信。

我认为以下示例代码不应产生递归特征 E0275 错误

可以转换为 i64 的简单类型:

enum MyNumbers {
    Zero,One,Two,}

impl From<MyNumbers> for i64 {
    fn from(n: MyNumbers) -> Self {
        match n {
            MyNumbers::Zero => 0,MyNumbers::One => 1,MyNumbers::Two => 2,}
    }
}

这里是一个可以在装饰器中使用的结构体:

struct MyWrapper<N> {
    n: N,}
如果 MyWrapper<N> 可以转换为 i64

N 可以转换为 i64

impl<N> From<MyWrapper<N>> for i64
where
    N: Into<i64>,{
    fn from(wrapper: MyWrapper<N>) -> Self {
        wrapper.n.into()
    }
}

Playground

这符合我的预期。

现在我希望能够从 i64 构造一个 MyWrapper 而无需消耗它。我更改了 From trait 实现以对引用进行操作:

impl From<&MyNumbers> for i64 {
    fn from(n: &MyNumbers) -> Self {
        match n {
            MyNumbers::Zero => 0,}
    }
}

impl<'a,N> From<&'a MyWrapper<N>> for i64
where
    &'a N: Into<i64>,{
    fn from(wrapper: &'a MyWrapper<N>) -> Self {
        (&wrapper.n).into()
    }
}

Playground

但是现在...

error[E0275]: overflow evaluating the requirement `i64: From<&MyWrapper<_>>`
  --> src/main.rs:34:13
   |
34 |     let i = i64::from(&w);
   |             ^^^^^^^^^
   |
   = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`playground`)
   = note: required because of the requirements on the impl of `Into<i64>` for `&MyWrapper<_>`
   = note: required because of the requirements on the impl of `From<&MyWrapper<MyWrapper<_>>>` for `i64`
   = note: 126 redundant requirements hidden
   = note: required because of the requirements on the impl of `From<&MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<MyWrapper<_>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` for `i64`

为什么这适用于拥有的类型,而不适用于引用?

另外,这真的让我很困惑—— 不调用 i64::from() 是可以的 - Playground
调用不同的 i64::from 错误 - 但不应该评估我的代码!? Playground

fn main() {
    i64::from(32i32);
}

解决方法

编译错误。 https://github.com/rust-lang/rust/issues/37748

作为一种解决方法,我不得不求助于 #[derive(Copy)] 以防止我的类型在转换的每个级别被消耗。也许 From/Into 不太适合这种模式......直到语言成熟一点。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。