使用泛型类型时,“From"的实现如何存在冲突? [英] How is there a conflicting implementation of `From` when using a generic type?

查看:33
本文介绍了使用泛型类型时,“From"的实现如何存在冲突?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to implement an error enum which can contain an error associated with one of our traits like this:

trait Storage {
    type Error;
}

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

我还尝试实现 From trait 以允许从 Storage::Error 的实例构建 MyError:

I have also tried to implement the From trait to allow construction of MyError from an instance of a 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<_>> 的实现(有),但我不想在这里实现它 - 我正在尝试实现FromMyError 与我所看到的 S::Error 的类型不同.

I don't understand why the compiler reckons this has already been implemented. The error message is telling me that there's already an implementation of From<MyError<_>> (which there is), but I'm not trying to implement that here - I'm trying to implement From<S::Error> and MyError is not the same type as S::Error from what I can see.

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

Am I missing something fundamental to generics here?

推荐答案

这里的问题是有人可能会实现 Storage 以便您编写的 From 实现与impl 标准库中的 impl来自<T>for T(即任何东西都可以转换为自身).

The problem here is someone may implement Storage so that the From impl you have written overlaps with the impl in the standard library of impl<T> From<T> for T (that is, anything can be converted to itself).

具体来说,

struct Tricky;

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

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

(The set-up here means this doesn't actually compile—MyError<Tricky> is infinitely large—but that error is unrelated to the reasoning about impls/coherence/overlap, and indeed small changes to MyError can make it compile without changing the fundamental problem, e.g. adding a Box like StorageProblem(Box<S::Error>),.)

如果我们在你的实现中用 Tricky 代替 S,我们得到:

If we substitute Tricky in place of S in your impl, we get:

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

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

This impl exactly matches the self-conversion one with T == MyError<Tricky>, and hence the compiler wouldn't know which one to choose. Instead of making an arbitrary/random choice, the Rust compiler avoids situations like this, and thus the original code must be rejected due to this risk.

这种连贯性限制肯定很烦人,这也是 专业化 是一个备受期待的功能:本质上允许手动指示编译器如何处理重叠......至少,其中一个扩展允许这样做.

This coherence restriction can definitely be annoying, and is one of reasons that specialisation is a much-anticipated feature: essentially allows manually instructing the compiler how to handle overlap... at least, one of the extensions to the current restricted form allows that.

这篇关于使用泛型类型时,“From"的实现如何存在冲突?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆