【问题标题】:Conflicting implementations of trait in RustRust 中 trait 的冲突实现
【发布时间】:2016-08-26 05:57:47
【问题描述】:

我想为&'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

&amp;'a str 没有实现Into&lt;i32&gt;。是否可以为&amp;'a str 实现UiId 以及可以转换为i32 的所有内容而不指定具体类型?我该怎么做?

【问题讨论】:

  • 我认为这一定是 Rust 确定实现是否重叠(或可能重叠)的限制,但我还没有找到任何地方说明规则的地方。 :-( 哦,对于正确的语言规范!

标签: generics rust traits


【解决方案1】:

&amp;'a str 没有实现Into&lt;i32&gt; 的事实不予考虑,因为不能保证以后不能添加。这会破坏你的代码。

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

很遗憾,我在The Rust Programming Language Book 和Reference Manual 中都找不到相关文档。

我能找到的最好的是RFC 1023,它表示一个板条箱[...] 不能依赖Type: !Trait 持有,除非TypeTrait 是本地的。 p>

【讨论】:

  • 我实际上不认为这是真的。这不就是孤儿规则的用途吗?您不能为外部类型添加外部特征 impls。在当前的 crate 中必须至少定义 trait 和 type 之一...为了让编译器对这样的情况进行推理,我认为
  • @LukasKalbertodt 查看我的编辑。它与 RFC 1023 中的 ophan 规则在同一个句子中。
  • 哦,确实,这听起来很合理。谢谢!
【解决方案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) {}
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 2018-08-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多