Rust 中 trait 的冲突实现
Posted
技术标签:
【中文标题】Rust 中 trait 的冲突实现【英文标题】:Conflicting implementations of trait in Rust 【发布时间】: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
&'a str
没有实现Into<i32>
。是否可以为&'a str
实现UiId
以及可以转换为i32
的所有内容而不指定具体类型?我该怎么做?
【问题讨论】:
我认为这一定是 Rust 确定实现是否重叠(或可能重叠)的限制,但我还没有找到任何地方说明规则的地方。 :-( 哦,对于正确的语言规范! 【参考方案1】:&'a str
没有实现Into<i32>
的事实不予考虑,因为不能保证以后不能添加。这会破坏你的代码。
因此,如果允许这样做,可能的破坏将使向库特征添加实现变得更加困难。
很遗憾,我在The Rust Programming Language Book 和Reference Manual 中都找不到相关文档。
我能找到的最好的是RFC 1023,它表示一个板条箱[...] 不能依赖Type: !Trait
持有,除非Type
或Trait
是本地的。 p>
【讨论】:
我实际上不认为这是真的。这不就是孤儿规则的用途吗?您不能为外部类型添加外部特征impl
s。在当前的 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)
【讨论】:
以上是关于Rust 中 trait 的冲突实现的主要内容,如果未能解决你的问题,请参考以下文章
如何使 Rust Generic Struct/Trait 需要 Box<other trait>?