Comparing Arc<T> T's by pointer

I had a question, but while writing this post I found the answer (turned out I was looking for the wrong name). Posting anyway in case someone else finds this interesting.


I need to check if a Arc<Foo> points to the same (as in the same memory address) Foo as a Option<Arc<Foo>> (assuming it is Some). For the purpose of my question I'll ignore the Option.

The documentation for the PartialEq implementation on Arc states that:

Equality for two Arcs.

Two Arcs are equal if their inner values are equal, even if they are stored in different allocation.

If T also implements Eq (implying reflexivity of equality), two Arcs that point to the same allocation are always equal.

(Emphasis mine)

How is this actually implemented?

I used this as a reference on godbolt:

use std::{ops::Range, sync::Arc};

#[derive(PartialEq, Eq)]
pub struct Foo {
  pub ranges: Vec<Range<usize>>,
  pub data: Vec<u8>
}

#[no_mangle]
pub fn comparatron(a: &Arc<Foo>, b: &Arc<Foo>) -> bool {
    a == b
}

When I compare -C opt-level=3 builds without and with Eq, I can see that the Eq causes the generation of:

        cmp     rcx, rsi
        je      .LBB0_7

(which is not present in the non-Eq build).

It's working as advertised -- but how is the implementation of Eq actually causing this?

Answering my own question: The implementation is, at the time of this writing, here. (Turns out the bound is crate::rc::MarkerEq and not Eq).

2 Likes

Arc adds its own address check before falling back to a full comparison.

There's ptr_eq if you just want to compare addresses and not the content.

5 Likes