E0119错误与通用特征实现

时间:2017-03-14 04:43:57

标签: generics rust traits

我有一个枚举:

enum Field {
    Str(String),
    Integer(i64),
}

我想这样做:

impl From<String> for Field {
    fn from(s: String) -> Field {
        Field::Str(s)
    }
}

impl<I> From<I> for Field where I: Into<i64> + Copy {
    fn from(i: I) -> Field {
        Field::Integer(Into::<i64>::into(i))
    }
}

上面的代码有错误:

error[E0119]: conflicting implementations of trait
`std::convert::From<std::string::String>` for type `Field`:
--> <anon>:12:5
   |
6  |          impl From<String> for Field {
   |  ________- starting here...
7  | |       fn from(s: String) -> Field {
8  | |         Field::Str(s)
9  | |       }
10 | |     }
   | |_____- ...ending here: first implementation here
11 | 
12 |       impl<I> From<I> for Field where I: Into<i64> + Copy {
   |  _____^ starting here...
13 | |       fn from(i: I) -> Field {
14 | |         Field::Integer(Into::<i64>::into(i))
15 | |       }
16 | |     }
   | |_____^ ...ending here: conflicting implementation for `Field`

String不是Into<i64>的实施者,为什么错误E0119会发生?

1 个答案:

答案 0 :(得分:4)

TL; DR:where条款不计算在内。

问题的关键在于冲突检测目前只是基于模式的:它不会考虑where条款。

问题是3倍:

  1. 确定where子句是否允许重叠是非常复杂的,
  2. 确定哪个where子句比另一个更专业是非常复杂的(即将推出的专业化),
  3. 允许否定推理意味着在库代码中添加特征实现现在是一个重大改变。
  4. 前两个是纯粹的实现细节,但后者在语言设计方面是一个真正的问题。想象一下:

    • 您的代码没有Copy绑定,
    • Rust团队决定简化解析并添加impl Into<i64> for &str

    突然间,发生了一场之前没有冲突的冲突!你无法升级!

    所以这里有一个真正的设计选择。你必须在:

    之间选择
    • 能够编写不冲突的impl,
    • 能够轻松升级您的依赖项。

    你不能同时拥有两者。

    注意:尝试在您选择的搜索引擎中输入Rust explain <code>,然后看E0119。虽然在这里没有那么有用。