rust - 使用泛型时, `From` 的实现如何冲突?

标签 rust

我正在尝试实现一个错误枚举,它可以包含与我们的特征之一相关联的错误,如下所示:

trait Storage {
    type Error;
}

enum MyError<S: Storage> {
    StorageProblem(S::Error),
}

我也尝试实现 From允许构造 MyError 的特征来自 Storage::Error 的实例:

impl<S: Storage> From<S::Error> for MyError<S> {
    fn from(error: S::Error) -> MyError<S> {
        MyError::StorageProblem(error)
    }
}

( playground )

但是编译失败:

error[E0119]: conflicting implementations of trait `std::convert::From<MyError<_>>` for type `MyError<_>`:
 --> src/lib.rs:9:1
  |
9 | impl<S: Storage> From<S::Error> for MyError<S> {
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: conflicting implementation in crate `core`:
          - impl<T> std::convert::From<T> for T;

我不明白为什么编译器认为这已经实现了。错误消息告诉我已经有一个 From<MyError<_>> 的实现。 (有),但我不是要在这里实现它 - 我正在尝试实现 From<S::Error>MyErrorS::Error 的类型不同据我所知。

我是否遗漏了一些泛型的基础知识?

最佳答案

这里的问题是有人可能会实现 Storage这样 From您编写的 impl 与 impl<T> From<T> for T 的标准库中的 impl 重叠(也就是说,任何东西都可以转化为自身)。

具体而言,

struct Tricky;

impl Storage for Tricky {
    type Error = MyError<Tricky>;
}

(这里的设置意味着这实际上并没有编译——MyError<Tricky> 是无限大的——但是这个错误与关于 impl s/coherence/overlap 的推理无关,而且实际上是对 MyError 的小改动。可以在不改 rebase 本问题的情况下编译它,例如添加一个 BoxStorageProblem(Box<S::Error>), 。)

如果我们替换 Tricky代替 S在您的暗示中,我们得到:

impl From<MyError<Tricky>> for MyError<Tricky> {
    ...
}

implT 完全匹配的自转换== MyError<Tricky> ,因此编译器不知道选择哪一个。 Rust 编译器没有做出任意/随机选择,而是避免了这种情况,因此由于这种风险,必须拒绝原始代码。

这种一致性限制肯定很烦人,这也是 specialisation 的原因之一是一个备受期待的功能:本质上允许手动指示编译器如何处理重叠......至少,one of the extensions当前的限制形式允许这样做。

关于rust - 使用泛型时, `From` 的实现如何冲突?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46383052/

相关文章:

rust - 引用和 Box<T> 在内存中的表示方式有什么区别?

intellij-idea - 如何为 IntelliJ 中的所有 Rust/Cargo 测试设置 --nocapture 标志?

Rust(新手): Read and write (mutable) access to the same underlying array from multiple threads for in-memory database?

macros - 如何在模块中定义和使用宏?

rust - Change selector in match when selector is a mutable reference

rust - 两个可变指针

rust - 是否所有原始类型都实现了 Copy 特性?

error-handling - std::error::FromError 惯用用法

rust - 无法使用f32.rs函数,链接器错误

rust - 如何使用 "r"或 "b"或类似的变量,而不是文字?