我正在尝试实现一个错误枚举,它可以包含与我们的特征之一相关的错误,如下所示:
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)
}
}
()
然而这无法编译:
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>
and MyError
与以下类型不同S::Error
据我所知。
我在这里遗漏了一些关于泛型的基本知识吗?
这里的问题是有人可能会实施Storage
所以这样From
您编写的 impl 与标准库中的 impl 重叠impl<T> From<T> for T
(也就是说,任何东西都可以转化为自身)。
具体来说,
struct Tricky;
impl Storage for Tricky {
type Error = MyError<Tricky>;
}
(这里的设置意味着这实际上并不能编译——MyError<Tricky>
是无限大的——但是这个错误与推理无关impl
s/连贯性/重叠,以及确实的小变化MyError
可以在不改变根本问题的情况下使其编译,例如添加一个Box
like StorageProblem(Box<S::Error>),
.)
如果我们替代Tricky
代替S
在你的实现中,我们得到:
impl From<MyError<Tricky>> for MyError<Tricky> {
...
}
This impl
与自转换完全匹配T
== MyError<Tricky>
,因此编译器不知道选择哪一个。 Rust 编译器不会做出任意/随机的选择,而是避免了这种情况,因此由于这种风险,原始代码必须被拒绝。
这种连贯性限制肯定会很烦人,也是原因之一专业化 https://github.com/rust-lang/rfcs/blob/master/text/1210-impl-specialization.md是一个备受期待的功能:本质上允许手动指示编译器如何处理重叠......至少,扩展之一 https://github.com/rust-lang/rfcs/blob/master/text/1210-impl-specialization.md#the-lattice-rule目前的限制形式允许这样做。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)