Skip to content

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

@mkoscumb

Description

@mkoscumb

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

Activity

added
A-diagnosticsArea: Messages for errors, warnings, and lints
T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
on Mar 25, 2024
added
D-confusingDiagnostics: Confusing error or lint that should be reworked.
on Mar 25, 2024
matthiaskrgr

matthiaskrgr commented on Mar 25, 2024

@matthiaskrgr
Member

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

kadiwa4 commented on Apr 20, 2024

@kadiwa4
Contributor

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.

added a commit that references this issue on Apr 23, 2024
added a commit that references this issue on May 9, 2024
estebank

estebank commented on Jul 1, 2024

@estebank
Contributor

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsD-confusingDiagnostics: Confusing error or lint that should be reworked.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @matthiaskrgr@estebank@kadiwa4@jieyouxu@mkoscumb

        Issue actions

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