Equality comparison causing a move?

Hi all,

I'm trying to make a generic equivalent of PartialEq for traits (Arc<dyn Foo>, specifically), and it almost works. Except that my toy example fails to compile because comparisons somehow seem to cause a move:

fn test(b: Baz) -> bool {
    b.op == b.op
}

fails with

error[E0505]: cannot move out of `b.op` because it is borrowed
   |
43 | fn test(b: Baz) -> bool {
   |         - binding `b` declared here
44 |     b.op == b.op
   |     ----    ^^^^ move out of `b.op` occurs here
   |     |
   |     borrow of `b.op` occurs here
   |
help: clone the value to increment its reference count
   |
44 |     b.op.clone() == b.op
   |         ++++++++

Changing it to

&b.op == &b.op

or

b.op.deref() == b.op.deref()

compiles fine... but that's not what #[derive(PartialEq)] does (my ultimate goal).

I assume the problem would be somewhere in deref coercion or other implicit trait use, but I can't guess what the culprit might be and there doesn't seem to be a way to make the compiler say what led it to that point.

What am I doing wrong?

I think this is a compiler bug; this appears to be a report with the same key code structure:

It is a longstanding bug.

There's an ergonomic workaround for Box<dyn Trait>, but I'm not sure about Arc<dyn Trait>. I'll play around and post again if I find one.

(As in, not requiring changes at the call site. *b.op == *b.op works.)

1 Like

Add this impl:

impl PartialEq<dyn Foo> for Arc<dyn Foo> {
    fn eq(&self, other: &dyn Foo) -> bool {
        (**self).dyn_eq((*other).any_ref())
    }
}

Thanks! It didn't occur to me that this might be a compiler bug, glad I asked.