Rust's pointer comparison don't compare the pointers, but the pointed-to values. This is the case for &T
, &mut T
, Box<T>
, Rc<T>
, Arc<T>
, etc., all but the raw pointers *const T
and *mut T
themselves. Those smart pointers usually have an extra method (std::rc::Rc::ptr_eq
in this case) for actual pointer comparison.
This is similar to how Debug
on those pointers prints the pointed-to value rather than the address, and you need the Pointer
trait to print the actual address: Rust isn't very address-focused.
Now, if you have a type such as f64
which doesn't have a transitive ==
(that is, it implements PartialEq
but not Eq
) and wrap it in an Rc
, you also get non-transitivity:
fn main() {
let a = std::rc::Rc::new(std::f64::NAN);
println!("a == a?: {}", a == a);
println!(
"a == a but with pointer comparison?: {}",
std::rc::Rc::ptr_eq(&a, &a)
);
// But:
let answer = std::rc::Rc::new(42);
// surely this will have a different address
let another_answer = std::rc::Rc::new(42);
println!("answer == another_answer?: {}", answer == another_answer);
}
prints:
a == a?: false
a == a but with pointer comparison?: true
answer == another_answer?: true
If T
happens to implement Eq
as well as PartialEq
, the current implementation indeed does a pointer comparison, using the yet-to-be-stabilized specialization feature.
See also: