Rust中特征的冲突实现

时间:2016-08-26 05:57:47

标签: generics rust implementation traits

我想为&'a str实现自定义特征,并为整数i32实现,但Rust不允许我:

use std::convert::Into;

pub trait UiId {
    fn push(&self);
}

impl<'a> UiId for &'a str {
    fn push(&self) {}
}

impl<T: Into<i32>> UiId for T {
    fn push(&self) {}
}

fn main() {}

无法使用以下错误进行编译:

error[E0119]: conflicting implementations of trait `UiId` for type `&str`:
  --> src/main.rs:11:1
   |
7  | impl<'a> UiId for &'a str {
   | ------------------------- first implementation here
...
11 | impl<T: Into<i32>> UiId for T {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&str`
   |
   = note: upstream crates may add new impl of trait `std::convert::From<&str>` for type `i32` in future versions

&'a str未实施Into<i32>。是否可以为UiId实现&'a str以及在不指定具体类型的情况下可以转换为i32的所有内容?我怎么能这样做?

2 个答案:

答案 0 :(得分:12)

&'a str未实现Into<i32>的事实未被考虑在内,因为无法保证以后无法添加Type: !Trait。这会破坏您的代码。

因此,如果允许这样做,可能的破坏将使得向库特征添加实现变得更加困难。

很遗憾,我无法在The Rust Programming Language书籍和Reference Manual中找到相关文档。

我能找到的最好的是RFC 1023,它表示除非TypeTrait@if(file_exists(public_path('/user_img/'.Auth::user()->id.'.jpg'))) ,否则一个箱子不能依赖false。局部的。

答案 1 :(得分:2)

我找到了一种使用标记特征的解决方法。无需夜间或实验性功能。诀窍是我在我的 crate 中定义了标记特征并且不导出它,因此上游 crate 不可能在我实现它的类以外的类上定义标记。

标记特征下方是 Numeric

我使用它是为了我可以为任何可以转换为 f64 的东西实现 Into,也可以为单独的 impl 中的字符串和其他类型实现。

Numeric trait 必须是 pub,因为它们警告未来版本将禁止在公共接口中使用私有 Trait。


use std::convert::Into;

pub trait Numeric {}
impl Numeric for f64 {}
impl Numeric for f32 {}
impl Numeric for i64 {}
impl Numeric for i32 {}
impl Numeric for i16 {}
impl Numeric for i8 {}
impl Numeric for isize {}
impl Numeric for u64 {}
impl Numeric for u32 {}
impl Numeric for u16 {}
impl Numeric for u8 {}
impl Numeric for usize {}


pub trait UiId {
    fn push(&self);
}

impl<'a> UiId for &'a str {
    fn push(&self) {}
}

impl<T: Into<i32> + Numeric> UiId for T {
    fn push(&self) {}
}