以下是演示此问题的玩具代码:
trait Foo {}
trait Boo<T> {
fn f() -> T;
}
impl<T> Boo<T> for i32
where
T: Foo,
{
fn f() -> T {
unimplemented!();
}
}
impl<'a, T> Boo<&'a T> for i32
where
T: Foo,
{
fn f() -> T {
unimplemented!();
}
}
我希望有trait Boo
的两个通用实现,但它没有编译:
error[E0119]: conflicting implementations of trait `Boo<&_>` for type `i32`:
--> src/main.rs:16:1
|
7 | / impl<T> Boo<T> for i32
8 | | where
9 | | T: Foo,
10 | | {
... |
13 | | }
14 | | }
| |_- first implementation here
15 |
16 | / impl<'a, T> Boo<&'a T> for i32
17 | | where
18 | | T: Foo,
19 | | {
... |
22 | | }
23 | | }
| |_^ conflicting implementation for `i32`
|
= note: downstream crates may implement trait `Foo` for type `&_`
我不打算将这部分功能用于其他包装箱。我试过了:
mod
pub(crate)
一切都没有成功。
反正有没有给编译器一个暗示,它不应该关心任何人会为任何引用实现Foo
?
也许我的玩具示例不是最好的,所以这是真正的代码。 它用于与我的程序的C部分集成,所以它有点 复杂。
impl<T: MyTrait> MyFrom<Option<T>> for *mut c_void {
fn my_from(x: Option<T>) -> Self {
match x {
Some(x) => <T>::alloc_heap_for(x),
None => ptr::null_mut(),
}
}
}
impl<'a, T: MyTrait> MyFrom<Option<&'a T>> for *mut c_void {
fn my_from(x: Option<&'a T>) -> Self {
match x {
Some(x) => x as *const T as *mut c_void,
None => ptr::null_mut(),
}
}
}
答案 0 :(得分:1)
这里的冲突与后一种实现的参考无关。问题在于,在第一个实现中,T
可以是 any 类型,包括引用类型。假设您进行以下函数调用:
let x: i32 = 10;
let result: &u8 = x.f();
这时,类型解析器需要弄清楚正在调用什么函数。它发现一个有冲突的实现:
impl Boo<&u8> for i32 via Boo<T> (T == &u8),
impl Boo<&u8> for i32 via Boo<&T> (T == u8),
如果在后一种实现中使用具体类型,则会遇到完全相同的问题:
// This will fail to compile
impl<T> Boo<T> for i32 { ... }
impl Boo<String> for i32 { ... }
此冲突意味着编译器不允许这两种实现共存。
您要在此处执行的特定操作称为“专业化”;它指的是针对一组规则的建议,该规则说如果这样的重叠实现中的一个明确地比另一个更“特定”,则允许存在这样的重叠实现,在这种情况下,编译器将选择更具体的实施。跟踪为RFC #1210。