有没有办法告诉编译器没有人会为泛型类型的引用实现特征? [英] Is there a way to tell the compiler that nobody will implement a trait for a reference to a generic type?

查看:30
本文介绍了有没有办法告诉编译器没有人会为泛型类型的引用实现特征?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是演示问题的玩具代码:

Here is toy code that demonstrates the problem:

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 的通用实现,但它不能编译:

I want to have two generic implementations of trait Boo, but it doesn't compile:

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 `&_`

我不打算将这部分功能用于其他板条箱.我试过了:

I do not plan to make this part of functionality to other crates. I tried:

  • 将此代码移动到显然不能从其他 crate 中使用的二进制 crate
  • 将其移动到私有 mod
  • 将特征标记为pub(crate)

都没有成功.

无论如何要给编译器一个提示,它不应该关心任何人会为任何参考实现Foo?

Is there anyway to give the compiler a hint that it should not care that anybody will implement Foo for any reference?

也许我的玩具示例不是最好的,所以这里是真正的代码.是用来和我程序的C部分集成的,所以有点复杂.

Maybe my toy example is not the best, so here is the real code. It's used for integration with the C part of my program, so it's a little complicated.

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

推荐答案

这里的冲突与后一个实现的引用无关.问题是,在第一个实现中,T 可以是任何类型,包括引用类型.假设您进行以下函数调用:

The conflict here doesn't have anything to do with the reference-ness of the latter implementation. The issue is that, in the first implementation, T can be any type, including reference types. Suppose you make the following function call:

let x: i32 = 10;
let result: &u8 = x.f();

此时,类型解析器需要弄清楚正在调用什么函数.它发现了一个冲突的实现:

At this point, the type resolver needs to figure out what function is being called. It finds a conflicting implementation:

impl Boo<&u8> for i32 via Boo<T>  (T == &u8),
impl Boo<&u8> for i32 via Boo<&T> (T == u8),

如果您在后一个实现中使用具体类型,您会遇到完全相同的问题:

You'd have exactly the same issue if you used a concrete type in the latter implementation:

// This will fail to compile
impl<T> Boo<T> for i32 { ... }
impl Boo<String> for i32 { ... }

这个冲突意味着编译器不能让这两种实现共存.

This conflict means that the compiler can't allow these two implementations to coexist.

您在这里要做的具体事情称为专业化";它指的是一组规则的提议,该规则表示允许存在这样的重叠实现如果其中一个比另一个更具体",在这种情况下编译器将选择更具体的实现.这被跟踪为 RFC #1210.

The specific thing you're looking to do here is called "specialization"; it refers to a proposal for a set of rules that says that overlapping implementations like this are allowed to exist if one of them is unambiguously more "specific" than the other, in which case the compiler will pick the more specific implementation. This is tracked as RFC #1210.

这篇关于有没有办法告诉编译器没有人会为泛型类型的引用实现特征?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆