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

#[derive(PartialEq)] fails to compile with an Arc<Trait> field #39128

Closed
sfackler opened this issue Jan 17, 2017 · 13 comments
Closed

#[derive(PartialEq)] fails to compile with an Arc<Trait> field #39128

sfackler opened this issue Jan 17, 2017 · 13 comments
Labels
C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@sfackler
Copy link
Member

use std::sync::Arc;
use std::fmt;
use std::cmp::PartialEq;

trait Foo {}

impl PartialEq for Foo {
    fn eq(&self, other: &Foo) -> bool {
        true
    }
}

type Bar = Arc<Foo>;

#[derive(PartialEq)]
struct Baz {
    bar: Bar,
}

fn main() {}
error[E0507]: cannot move out of borrowed content
  --> foo.rs:17:5
   |
17 |     bar: Bar,
   |     ^^^^^^^^ cannot move out of borrowed content

error[E0507]: cannot move out of borrowed content
  --> foo.rs:17:5
   |
17 |     bar: Bar,
   |     ^^^^^^^^ cannot move out of borrowed content

error: aborting due to 2 previous errors

Expanded:

#![feature(prelude_import)]
#![no_std]
#[prelude_import]
use std::prelude::v1::*;
#[macro_use]
extern crate std as std;
use std::sync::Arc;
use std::fmt;
use std::cmp::PartialEq;

trait Foo { }

impl PartialEq for Foo {
    fn eq(&self, other: &Foo) -> bool { true }
}

type Bar = Arc<Foo>;

struct Baz {
    bar: Bar,
}
#[automatically_derived]
#[allow(unused_qualifications)]
impl ::std::cmp::PartialEq for Baz {
    #[inline]
    fn eq(&self, __arg_0: &Baz) -> bool {
        match *__arg_0 {
            Baz { bar: ref __self_1_0 } =>
            match *self {
                Baz { bar: ref __self_0_0 } =>
                true && (*__self_0_0) == (*__self_1_0),
            },
        }
    }
    #[inline]
    fn ne(&self, __arg_0: &Baz) -> bool {
        match *__arg_0 {
            Baz { bar: ref __self_1_0 } =>
            match *self {
                Baz { bar: ref __self_0_0 } =>
                false || (*__self_0_0) != (*__self_1_0),
            },
        }
    }
}

fn main() { }
@sfackler
Copy link
Member Author

The derefs of the __self_1_0 fields appear to be the issues - we should just be able to remove those from the derived output since references forward equality, right?

@sfackler sfackler added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Jan 17, 2017
@brson brson added the I-wrong label Jan 18, 2017
@Mark-Simulacrum Mark-Simulacrum added C-bug Category: This is a bug. and removed I-wrong labels Jul 26, 2017
@stephaneyfx
Copy link
Contributor

It looks related to #31740.

@dtolnay
Copy link
Member

dtolnay commented Jan 28, 2018

Same thing for Box<Trait> as reported in #47823.

trait Trait {}

impl PartialEq for Box<Trait> {
    fn eq(&self, _: &Box<Trait>) -> bool {
        false
    }
}

#[derive(PartialEq)]
struct S(Box<Trait>);

The generated code looks like:

impl PartialEq for S {
    fn eq(&self, rhs: &S) -> bool {
        match *rhs {
            S(ref rhs) => match *self {
                S(ref lhs) => true && (*lhs) == (*rhs)
            }
        }
    }
}
error[E0507]: cannot move out of borrowed content
  --> src/main.rs:18:49
   |
18 |                 S(ref lhs) => true && (*lhs) == (*rhs)
   |                                                 ^^^^^^ cannot move out of borrowed content

@shepmaster
Copy link
Member

This seems like a duplicate of #31740, as @stephaneyfx mentioned. Any reason to not close it as such?

@daboross
Copy link
Contributor

daboross commented Apr 21, 2018

It should be possible to fix this issue without fixing the underlying one though, right?

I'd appreciate it if this was fixed to work in #[derive(PartialEq)] even if regular == still failed.

Ideally it would also be nice to get an error message that this comes from #[derive(PartialEq)] in cases like this - not sure how possible that is, though. It was at least a bit confusing running into this error just on the field itself, and having to do elimination to find out that it was PartialEq doing it.

@Diggsey
Copy link
Contributor

Diggsey commented Feb 28, 2019

Ugh, just ran into this today 😢

@spease
Copy link

spease commented May 9, 2019

I'm also getting this.

@TheNeikos
Copy link
Contributor

TheNeikos commented Aug 12, 2019

I just ran into this problem and solved it (for now) by using a newtype like this:

Where before I had:

#[derive(PartialEq)
struct Foo(Box<dyn Trait>);

I now have:

struct BoxedTrait(Box<dyn Trait>);

impl PartialEq for BoxedTrait {
   fn eq(&self, other: &Self) -> bool {
    <Box<dyn Trait> as PartialEq>::eq(&self.0, &other.0)
  }
}

#[derive(PartialEq)
struct Foo(BoxedTrait);

@ColonelThirtyTwo
Copy link

Also ran into this. Though unlike the other examples, I was implementing PartialEq on the dynamic trait object itself rather than Box<Trait>.

@garfieldnate
Copy link

I'm also struggling with this; I tried the solution from @TheNeikos, but Rust tells me that the 0 field of Box is private. Can I use something else instead of the 0 field?

@garfieldnate
Copy link

I went with this to achieve simple pointer equality:

use std::ptr;
type BoxedMyTrait = Box<dyn MyTrait>;

impl PartialEq for BoxedMyTrait {
	fn eq(&self, other: &Self) -> bool {
		ptr::eq(self as *const _, other as *const _)
	}
}

@daboross
Copy link
Contributor

@garfieldnate @TheNeikos's solution is for a tuple struct with a single field. The .0 here isn't accessing .0 of a box, but .0 of the tuple struct (in other words, the box).

I believe your situation is a different issue.

@Enselic
Copy link
Member

Enselic commented Dec 10, 2023

Triage: Let's close as duplicate to duplicate of #31740. It seems much to fix the underlying issue rather than special casing a fix for just #[derive(PartialEq)].

@Enselic Enselic closed this as not planned Won't fix, can't repro, duplicate, stale Dec 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
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