在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;
}
如playground所示,这表明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;
}
我们可以see Eq
未fn(&u32) -> u32
实施{/ 1}}:
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
这是故意的,疏忽,应该实施,还是错误? 如果是第一个,那么不这样做的原因是什么?
查看the source code for fn
,我们看到它们使用原始指针等价实现PartialEq
,即如果地址相同,则它必须是相同的函数。为什么这不适用于fn(&T) -> T
?
向我呈现的一个选项是fn(&T) -> T
在参数的生命周期内是通用的,因此不能逻辑Eq
。 fn(&'a T) -> T
不是通用的,因为生命周期已指定为'a
。我不太确定我接受/理解这个假设,所以如果有人有一个好的论据,我也会接受。
答案 0 :(得分:2)
可能是因为当您比较两个fn(&T) -> T
时,您真正将fn(&'a T) -> T
与fn(&'b T) -> T
进行比较,无法检查生命周期'a
和{ {1}}是相同的,而当您比较两个'b
时,您知道生命周期是相同的。
注意:这只是我的假设,我没有关于此事的权威信息。