Rust中特征的冲突实现

Sla*_*nov 11 generics implementation traits rust

我想实现一个自定义特征&'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() {}
Run Code Online (Sandbox Code Playgroud)

无法编译时出现以下错误:

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
Run Code Online (Sandbox Code Playgroud)

&'a str没有实现Into<i32>.是否可以实现UiIdfor &'a str和所有可以转换成的内容i32而无需指定具体类型?我怎样才能做到这一点?

sta*_*lue 12

&'a str未实施的事实Into<i32>不予考虑,因为无法保证以后无法添加.这会破坏你的代码.

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

遗憾的是,我无法在"Rust编程语言手册"和" 参考手册 "中找到相关文档.

我能找到的最好的是RFC 1023,它说,一箱[...]不能依靠的是Type: !Trait持有,除非Type或者Trait是本地的.


Pau*_*och 12

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

标记特征下方是Numeric

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

Numeric特征一定是pub因为他们警告未来的版本将不允许在公共接口中使用私有特征。


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) {}
}

Run Code Online (Sandbox Code Playgroud)