Take the following valid snippet in 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;
}
As seen on the playground, this shows that Eq
is implemented for fn(&'a T) -> T
.
If we make a very small change, removing the lifetime of the associated type:
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;
}
We can see that Eq
is not implemented for 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
Is this intentional, an oversight and should be implemented, or a bug? If it's the first, what are the reasons for not doing it?
Looking at the source code for fn
, we see that they implement PartialEq
using raw pointer equivalence, i.e. if the address is the same, it must be the same function. Why would this not hold for fn(&T) -> T
?
One option that has been presented to me is that fn(&T) -> T
is generic over the lifetime of the argument and cannot therefore be logically Eq
. fn(&'a T) -> T
is not generic, as the lifetime has been specified to be 'a
. I'm not quite sure I accept/understand this hypothesis so if anyone has a good argument for it I would accept that too.
Trait for equality comparisons which are partial equivalence relations. This trait allows for partial equality, for types that do not have a full equivalence relation. For example, in floating point numbers NaN !=
Probably because when you compare two fn(&T) -> T
, you're really comparing an fn(&'a T) -> T
with an fn(&'b T) -> T
with no way to check that the lifetimes 'a
and 'b
are the same, whereas when you compare two fn(&'a T) -> T
, you know that the lifetimes are the same.
Note: this is only a supposition on my part, I have no authoritative information on the matter.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With