Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem with PartialEq #67369

Open
zakarumych opened this issue Dec 17, 2019 · 5 comments
Open

Problem with PartialEq #67369

zakarumych opened this issue Dec 17, 2019 · 5 comments
Labels
A-DSTs Area: Dynamically-sized types (DSTs) C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@zakarumych
Copy link
Contributor

zakarumych commented Dec 17, 2019

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

@jonas-schievink jonas-schievink added A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Dec 17, 2019
@cuviper
Copy link
Member

cuviper commented Dec 18, 2019

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.

@cuviper
Copy link
Member

cuviper commented Dec 18, 2019

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
}

@cuviper
Copy link
Member

cuviper commented Dec 18, 2019

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

Comparison: c2b30b8...e539424

$ 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() {}

@cuviper
Copy link
Member

cuviper commented Dec 18, 2019

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

@nrc nrc changed the title Problem with derived PartialEq Problem with PartialEq Dec 18, 2019
@nrc nrc removed the A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) label Dec 18, 2019
@Spoonbender
Copy link

triage: no change

@Enselic Enselic added the A-DSTs Area: Dynamically-sized types (DSTs) label May 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-DSTs Area: Dynamically-sized types (DSTs) C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

6 participants