Rust: Problem with `PartialEq`

Created on 17 Dec 2019  路  4Comments  路  Source: rust-lang/rust

When I try to derive(PartialEq) for type I get weird compilation error in generated code, but I'm sure it should be fine.

Here's link to playground

C-bug T-compiler

Most helpful comment

I went nightly-bisecting -- it works on nightly-2015-05-13, and fails on 2015-05-14.

Comparison: https://github.com/rust-lang/rust/compare/c2b30b86df6b34ba19e87e63402e43d9e81a64fb...e5394240a295650b567aa406b4a0e1e3a6749a5f

$ rustc +nightly-2015-05-13 -Vv
rustc 1.1.0-nightly (c2b30b86d 2015-05-12) (built 2015-05-13)
binary: rustc
commit-hash: c2b30b86df6b34ba19e87e63402e43d9e81a64fb
commit-date: 2015-05-12
build-date: 2015-05-13
host: x86_64-unknown-linux-gnu
release: 1.1.0-nightly

$ rustc +nightly-2015-05-13 issue67369.rs
issue67369.rs:1:1: 3:2 warning: struct is never used: `Foo`, #[warn(dead_code)] on by default
issue67369.rs:1 struct Foo<T: ?Sized> {
issue67369.rs:2     value: T,
issue67369.rs:3 }
issue67369.rs:2:5: 2:13 warning: struct field is never used: `value`, #[warn(dead_code)] on by default
issue67369.rs:2     value: T,
                    ^~~~~~~~
issue67369.rs:11:1: 13:2 warning: struct is never used: `Bar`, #[warn(dead_code)] on by default
issue67369.rs:11 struct Bar {
issue67369.rs:12     ptr: Box<Foo<Trait>>,
issue67369.rs:13 }


$ rustc +nightly-2015-05-14 -Vv
rustc 1.1.0-nightly (e5394240a 2015-05-14) (built 2015-05-14)
binary: rustc
commit-hash: e5394240a295650b567aa406b4a0e1e3a6749a5f
commit-date: 2015-05-14
build-date: 2015-05-14
host: x86_64-unknown-linux-gnu
release: 1.1.0-nightly

$ rustc +nightly-2015-05-14 issue67369.rs
issue67369.rs:17:21: 17:26 error: cannot move out of borrowed content
issue67369.rs:17         self.ptr == other.ptr
                                     ^~~~~
error: aborting due to previous error

That 1.0-compatible test source again:

struct Foo<T: ?Sized> {
    value: T,
}

impl<T: ?Sized> PartialEq for Foo<T> {
    fn eq(&self, _: &Self) -> bool { true }
}

trait Trait {}

struct Bar {
    ptr: Box<Foo<Trait>>,
}

impl PartialEq for Bar {
    fn eq(&self, other: &Self) -> bool {
        self.ptr == other.ptr
    }
}

fn main() {}

All 4 comments

I simplified your example slightly to Box, and also changed to a manual impl, and it still fails:

struct Foo<T: ?Sized> {
    value: T,
}

impl<T: ?Sized> PartialEq for Foo<T> {
    fn eq(&self, _: &Self) -> bool { true }
}

trait Trait {}

struct Bar {
    ptr: Box<Foo<dyn Trait>>,
}

impl PartialEq for Bar {
    fn eq(&self, other: &Self) -> bool {
        self.ptr == other.ptr
    }
}

fn main() {}

(playground)

error[E0507]: cannot move out of `other.ptr` which is behind a shared reference
  --> src/main.rs:17:21
   |
17 |         self.ptr == other.ptr
   |                     ^^^^^^^^^ move occurs because `other.ptr` has type `std::boxed::Box<Foo<dyn Trait>>`, which does not implement the `Copy` trait

If you change Foo<dyn Trait> to Foo<Trait>, this can even be reproduced on really old versions of Rust, all the way back to 1.1 -- however Rust 1.0 accepts it!

Changing to &self.ptr == &other.ptr works. PartialEq for & just calls UFCS, which also works here, Foo::eq(&self.ptr, &other.ptr). But of course you can't make #[derive(PartialEq)] do that.

It does work generically, even instantiated with the same type:

// Foo and Trait as before

struct Bar<T: ?Sized> {
    ptr: Box<Foo<T>>,
}

impl<T: ?Sized> PartialEq for Bar<T> {
    fn eq(&self, other: &Self) -> bool {
        self.ptr == other.ptr
    }
}

fn eq(a: Bar<dyn Trait>, b: Bar<dyn Trait>) -> bool {
    a == b
}

I went nightly-bisecting -- it works on nightly-2015-05-13, and fails on 2015-05-14.

Comparison: https://github.com/rust-lang/rust/compare/c2b30b86df6b34ba19e87e63402e43d9e81a64fb...e5394240a295650b567aa406b4a0e1e3a6749a5f

$ rustc +nightly-2015-05-13 -Vv
rustc 1.1.0-nightly (c2b30b86d 2015-05-12) (built 2015-05-13)
binary: rustc
commit-hash: c2b30b86df6b34ba19e87e63402e43d9e81a64fb
commit-date: 2015-05-12
build-date: 2015-05-13
host: x86_64-unknown-linux-gnu
release: 1.1.0-nightly

$ rustc +nightly-2015-05-13 issue67369.rs
issue67369.rs:1:1: 3:2 warning: struct is never used: `Foo`, #[warn(dead_code)] on by default
issue67369.rs:1 struct Foo<T: ?Sized> {
issue67369.rs:2     value: T,
issue67369.rs:3 }
issue67369.rs:2:5: 2:13 warning: struct field is never used: `value`, #[warn(dead_code)] on by default
issue67369.rs:2     value: T,
                    ^~~~~~~~
issue67369.rs:11:1: 13:2 warning: struct is never used: `Bar`, #[warn(dead_code)] on by default
issue67369.rs:11 struct Bar {
issue67369.rs:12     ptr: Box<Foo<Trait>>,
issue67369.rs:13 }


$ rustc +nightly-2015-05-14 -Vv
rustc 1.1.0-nightly (e5394240a 2015-05-14) (built 2015-05-14)
binary: rustc
commit-hash: e5394240a295650b567aa406b4a0e1e3a6749a5f
commit-date: 2015-05-14
build-date: 2015-05-14
host: x86_64-unknown-linux-gnu
release: 1.1.0-nightly

$ rustc +nightly-2015-05-14 issue67369.rs
issue67369.rs:17:21: 17:26 error: cannot move out of borrowed content
issue67369.rs:17         self.ptr == other.ptr
                                     ^~~~~
error: aborting due to previous error

That 1.0-compatible test source again:

struct Foo<T: ?Sized> {
    value: T,
}

impl<T: ?Sized> PartialEq for Foo<T> {
    fn eq(&self, _: &Self) -> bool { true }
}

trait Trait {}

struct Bar {
    ptr: Box<Foo<Trait>>,
}

impl PartialEq for Bar {
    fn eq(&self, other: &Self) -> bool {
        self.ptr == other.ptr
    }
}

fn main() {}

24619 is part of that change list, and seems potentially relevant. cc @nrc

Was this page helpful?
0 / 5 - 0 ratings