有意为fn(&'a T)实现cmp :: Eq - > T但不是fn(& T) - > T'

时间:2018-03-29 23:48:33

标签: rust

在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 Eqfn(&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在参数的生命周期内是通用的,因此不能逻辑Eqfn(&'a T) -> T不是通用的,因为生命周期已指定为'a。我不太确定我接受/理解这个假设,所以如果有人有一个好的论据,我也会接受。

1 个答案:

答案 0 :(得分:2)

可能是因为当您比较两个fn(&T) -> T时,您真正将fn(&'a T) -> Tfn(&'b T) -> T进行比较,无法检查生命周期'a和{ {1}}是相同的,而当您比较两个'b时,您知道生命周期是相同的。

注意:这只是我的假设,我没有关于此事的权威信息。