Skip to content

Using derive(PartialEq) on an enum with a variant that accepts(Box<dyn SomeTrait>) causes cryptic build error. #123056

New issue

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

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

Already on GitHub? # to your account

Closed
mkoscumb opened this issue Mar 25, 2024 · 3 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints D-confusing Diagnostics: Confusing error or lint that should be reworked. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@mkoscumb
Copy link

Code

trait Animal {
    fn noise(&self) -> String;
}

struct Cat {}

impl Animal for Cat {
    fn noise(&self) -> String {
        "Meow".to_owned()
    }
}

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

#[derive(PartialEq)]
enum Things {
    Animal(Box<dyn Animal>),
    Vegitable,
}

fn use_thing(thing: Things) {
    match thing {
        Things::Animal(animal) => {
            println!("{}", animal.noise())
        }
        Things::Vegitable => {
            println!("Yuck!")
        }
    }
}

fn main() {
    let kitty = Cat {};
    use_thing(Things::Animal(Box::new(kitty)));
    use_thing(Things::Vegitable);
}

Current output

Compiling playground v0.0.1 (/playground)
error[E0507]: cannot move out of `*__arg1_0` which is behind a shared reference
  --> src/main.rs:21:12
   |
19 | #[derive(PartialEq)] // To fix error, comment out this line and uncomment 25-34
   |          --------- in this derive macro expansion
20 | enum Things {
21 |     Animal(Box<dyn Animal>),
   |            ^^^^^^^^^^^^^^^ move occurs because `*__arg1_0` has type `Box<dyn Animal>`, which does not implement the `Copy` trait
   |
   = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)

For more information about this error, try `rustc --explain E0507`.
error: could not compile `playground` (bin "playground") due to 1 previous error

Desired output

Either it should succeed or generate a better error message.

Rationale and extra context

No response

Other cases

No response

Rust Version

Repro in playground.
rustc 1.77.0

Anything else?

Playground link:
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=423832065e26b689e7aa16b31c96275c

@mkoscumb mkoscumb added A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Mar 25, 2024
@jieyouxu jieyouxu added the D-confusing Diagnostics: Confusing error or lint that should be reworked. label Mar 25, 2024
@matthiaskrgr
Copy link
Member

matthiaskrgr commented Mar 25, 2024

this regressed in nightly-2019-06-05 :)
with 2019 06 04 this gave

error[E0507]: cannot move out of borrowed content
  --> /tmp/crash.rs:21:12
   |
21 |     Animal(Box<dyn Animal>),
   |            ^^^^^^^^^^^^^^^ cannot move out of borrowed content

error: aborting due to previous error

ending github query because we found starting sha: 6ffb8f5
get_commits_between returning commits, len: 8
commit[0] 2019-06-03: Auto merge of #61100 - varkor:must_use-tuple-expr, r=cramertj
commit[1] 2019-06-03: Auto merge of #59148 - lcnr:unchecked_maths, r=eddyb
commit[2] 2019-06-04: Auto merge of #61467 - Manishearth:clippyup, r=Manishearth
commit[3] 2019-06-04: Auto merge of #61510 - Centril:rollup-bvi95y2, r=Centril
commit[4] 2019-06-04: Auto merge of #61136 - matthewjasper:cannot-move-errors, r=pnkfelix
commit[5] 2019-06-04: Auto merge of #61437 - christianpoveda:const-eval-indirects, r=wesleywiser,oli-obk
commit[6] 2019-06-04: Auto merge of #61454 - lzutao:ice-rotate_left, r=RalfJung
commit[7] 2019-06-04: Auto merge of #61407 - phansch:annotate_snippet_refactoring1, r=oli-obk
ERROR: no CI builds available between 6ffb8f5 and 5d8f59f within last 167 days

@kadiwa4
Copy link
Contributor

kadiwa4 commented Apr 20, 2024

This can occur outside of derives too (playground):

trait Animal {
    fn noise(&self) -> String;
}

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

fn f(a1: &Box<dyn Animal>, a2: &Box<dyn Animal>) {
    println!("{}", *a1 == *a2); // doesn't work
}

According to the reference, this should be equivalent to:

fn f(a1: &Box<dyn Animal>, a2: &Box<dyn Animal>) {
    println!("{}", PartialEq::eq(&*a1, &*a2)); // works
}

That means both versions should compile if I understand correctly (because the latter version does compile).

It seems to be specific to trait objects; e.g. replacing Box<dyn Animal> with Box<[String]> will make both versions of f compile.

bors added a commit to rust-lang-ci/rust that referenced this issue Apr 23, 2024
Do not add leading asterisk in the `PartialEq`

I think we should address this issue, however I am not exactly sure, if this is the right way to do it. It is related to the rust-lang#123056.

Imagine the simplified code:

```rust
trait MyTrait {}

impl PartialEq for dyn MyTrait {
    fn eq(&self, _other: &Self) -> bool {
        true
    }
}

#[derive(PartialEq)]
enum Bar {
    Foo(Box<dyn MyTrait>),
}
```

On the nightly compiler, the `derive` produces invalid code with the weird error message:
```
error[E0507]: cannot move out of `*__arg1_0` which is behind a shared reference
  --> src/main.rs:11:9
   |
9  | #[derive(PartialEq)]
   |          --------- in this derive macro expansion
10 | enum Things {
11 |     Foo(Box<dyn MyTrait>),
   |         ^^^^^^^^^^^^^^^^ move occurs because `*__arg1_0` has type `Box<dyn MyTrait>`, which does not implement the `Copy` trait
   |
   = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
```

It may be related to the perfect derive problem, although requiring the _type_ to be `Copy` seems unfortunate because it is not necessary. Besides, we are adding the extra dereference only for the diagnostics?
bors added a commit to rust-lang-ci/rust that referenced this issue May 9, 2024
Do not add leading asterisk in the `PartialEq`

I think we should address this issue, however I am not exactly sure, if this is the right way to do it. It is related to the rust-lang#123056.

Imagine the simplified code:

```rust
trait MyTrait {}

impl PartialEq for dyn MyTrait {
    fn eq(&self, _other: &Self) -> bool {
        true
    }
}

#[derive(PartialEq)]
enum Bar {
    Foo(Box<dyn MyTrait>),
}
```

On the nightly compiler, the `derive` produces invalid code with the weird error message:
```
error[E0507]: cannot move out of `*__arg1_0` which is behind a shared reference
  --> src/main.rs:11:9
   |
9  | #[derive(PartialEq)]
   |          --------- in this derive macro expansion
10 | enum Things {
11 |     Foo(Box<dyn MyTrait>),
   |         ^^^^^^^^^^^^^^^^ move occurs because `*__arg1_0` has type `Box<dyn MyTrait>`, which does not implement the `Copy` trait
   |
   = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
```

It may be related to the perfect derive problem, although requiring the _type_ to be `Copy` seems unfortunate because it is not necessary. Besides, we are adding the extra dereference only for the diagnostics?
@estebank
Copy link
Contributor

estebank commented Jul 1, 2024

Triage: the original case is now properly handled, but the move error issue on == desugaring still remains. Opened #127215 for it.

@estebank estebank closed this as completed Jul 1, 2024
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints D-confusing Diagnostics: Confusing error or lint that should be reworked. 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

5 participants