在Rust 1.25.0中获取以下有效代码段:
use std::marker::PhantomData;
trait Foo {
type Eq: Eq;
}
struct Bar<'a>(PhantomData<&'a u8>);
impl<'a> Foo for Bar<'a> {
type Eq = fn(&'a u32) -> u32;
}
Run Code Online (Sandbox Code Playgroud)
正如在操场上看到的那样,这表明Eq已经实现了fn(&'a T) -> T.
如果我们进行非常小的更改,则删除关联类型的生命周期:
use std::marker::PhantomData;
trait Foo {
type Eq: Eq;
}
struct Bar<'a>(PhantomData<&'a u8>);
impl<'a> Foo for Bar<'a> {
type Eq = fn(&u32) -> u32;
}
Run Code Online (Sandbox Code Playgroud)
我们可以看到这Eq是不是为实现fn(&u32) -> u32:
error[E0277]: the trait bound `for<'r> fn(&'r u32) -> u32: std::cmp::Eq` is not satisfied
--> src/main.rs:9:10
|
9 | impl<'a> Foo for Bar<'a> {
| ^^^ the trait `std::cmp::Eq` is not implemented for `for<'r> fn(&'r u32) -> u32`
|
= help: the following implementations were found:
<extern "C" fn(A) -> Ret as std::cmp::Eq>
<unsafe fn(A) -> Ret as std::cmp::Eq>
<extern "C" fn(A, ...) -> Ret as std::cmp::Eq>
<unsafe extern "C" fn(A, ...) -> Ret as std::cmp::Eq>
and 2 others
Run Code Online (Sandbox Code Playgroud)
这是故意的,疏忽,应该实施,还是一个错误?如果是第一个,那么不这样做的原因是什么?
查看源代码fn,我们看到它们PartialEq使用原始指针等价实现,即如果地址相同,则它必须是相同的函数.为什么这不适合fn(&T) -> T?
提交给我的一个选项fn(&T) -> T是在参数的生命周期内是通用的,因此不能在逻辑上Eq.fn(&'a T) -> T不是通用的,因为生命周期已被指定为'a.我不太确定我是否接受/理解这个假设,所以如果有人对此有充分的论据,我也会接受.
可能是因为当您比较两个时fn(&T) -> T,您实际上是在比较一个fn(&'a T) -> T与一个fn(&'b T) -> T,无法检查生命周期'a和'b是否相同,而当您比较两个时fn(&'a T) -> T,您知道生命周期是相同的。
注:这只是我的猜测,我没有这方面的权威信息。