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/53330919/

相关文章:

rust - 如何在循环中更新可变引用?

arrays - 将已知的编译时大小切片到数组,绝对正确

rust - 如何创建一个接受 i32s 迭代器作为值或引用并对它们求和的函数?

windows - 我应该使用哪个版本的 gcc 来正确构建 ruSTLearn crate?

rust - 实现可在不同类型的所有权 : &'a T, 或 Box<T> 或 A : T? 上重用的通用代码的最佳实践是什么

rust - 使用铁框架,如何退出监听循环?

rust - 如何使用对受 Arc<RwLock<T>> 保护的基础数据的引用?

Rust 无法从 Any 扩展的特征对象向下转换引用

closures - 如何为闭包参数声明更高级别的生命周期?

rust - 我在哪里可以找到 Rust 编程语言书中提到的源代码(.rs 文件)?