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

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

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in 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