Blog
网站首页
Rust实现trait时出现conflicting implementations的原因
Rust实现trait时出现conflicting implementations的原因
2024-05-23 16:01
2024-05-30 14:50
作者:
xmh0511
提交
#### 1. 当对于同一个`Trait`存在多份对于同一个类型的**可用**实现,编译器就会报错,类似 > conflicting implementations of trait `Trait` for type `Type` 这里的同一个`Trait`是指当对`Trait
`中的type parameters带入所有实际值之后形成的`Trait`相同,同一个类型也是类似概念,即`Type
`为`U`带入实际类型后形成的类型相同。 而**可用**是指如果实现有约束,那么所有存在的约束要被满足才能成为**可用**实现。 此外对于给定类型,如果该类型和约束是non-local的,那么编译器会假定该类型施加的那个non-local的约束会在未来某个时刻有可能由依赖的包实现,从而变成可用实现。 ```rust trait Trait
{} impl Trait<()> for u8{} // #1 impl Trait
for u8{} //#2 ``` 这里的`Trait<()>`与`Trait
`就不是同一个`Trait`, 因此`#1`和`#2`不是冲突的实现。 #### 2. 对于 > conflicting implementations of trait `xx` for type `yy` upstream crates may add a new impl of trait `xx` for type `yy` in future versions 编译器报告的错误的解释,例如 ```rust trait Trait{} struct A
(T); impl
> Trait for A
{} // #1 impl Trait for A
{} ``` 当`#1`中的`T`为`String`并且当`String: Into
`时会形成对同一个类型和同一个`Trait`存在多份实现,虽然目前标准库并没有为`String`实现`Into
`或者说为`u8`实现`From
`, 但从编译器角度来看`Into
`这个`Trait`和类型`String`都不是local的,并且他们都是上游crate定义的实体,因此如果将来上游crate实现了Trait使得`String:Into
`,那么就会造成下游也就是当前这个crate产生冲突实现,因此编译器拒绝,如果这里的`T`是本地类型,即 ```rust trait Trait{} struct A
(T); struct D; impl
> Trait for A
{} // #1 impl Trait for A
{} ``` 就不会存在这个问题了。 #### 3. 对于 > conflicting implementations of trait `xx` for type `yy` downstream crates may implement trait `xx` for type `yy` 编译器报告的错误的解释,例如 ```rust trait Trait
{ } trait Other
{ } struct Test; impl
,U> Trait
for T{} // #1 impl
Trait
for Test{} ``` 这里存在`U`如果带入下游crate定义的类型,比如 ```rust struct DownStream; impl upstream::Other
for upstream::Test{} ``` 虽然`upstream::Test`和`upstream::Other`都是上游定义的,即不是local的,但根据[Concrete orphan rules](https://rust-lang.github.io/rfcs/2451-re-rebalancing-coherence.html#concrete-orphan-rules), 这是一个合法的实现,因此当下游存在这么一个可用实现时,对于上游的blanket实现`#1`,当`T = Test`且`U`是`downstream::DownStream`,那么就会导致上游crate中对同一个类型`Test`和同一个`Trait
`存在两份**可用实现**,因为`#1`的约束`Test:Other
`是满足的。因此编译器报告了该错误。 #### 4. 对于存在不同约束的两个blanket impls > conflicting implementations of trait `XXX` ```rust trait Handle {} impl Handle for i32 {} trait Unified { fn push(self); } impl
Unified for T where T: IntoIterator, T::Item: Handle, { fn push(self) { println!("first"); } } impl
Unified for T where T: Handle, { fn push(self) { println!("second"); } } ``` 此例中,虽然两个实现有着不同的约束,但依然可以存在某个具体类型`Type`使得两个实现的约束都被满足,从而出现同一个trait和同一个类型存在多个可用实现。