有没有办法告诉编译器没有人会实现引用泛型类型的特征?

时间:2018-04-25 01:22:01

标签: rust

以下是演示此问题的玩具代码:

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(),
        }
    }
}

1 个答案:

答案 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