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

Weird errors with dyn Traits in enums #117974

Closed
Cerber-Ursi opened this issue Nov 16, 2023 · 2 comments
Closed

Weird errors with dyn Traits in enums #117974

Cerber-Ursi opened this issue Nov 16, 2023 · 2 comments
Labels
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.

Comments

@Cerber-Ursi
Copy link
Contributor

Cerber-Ursi commented Nov 16, 2023

Code

pub trait A {}

impl PartialEq for dyn A {
    fn eq(&self, _: &Self) -> bool {
        todo!()
    }
}

// First case: enum contains the reference, equality is checked directly
mod first_case {
    pub enum E<'a> {
        V(&'a dyn crate::A),
    }

    impl<'a> ::core::cmp::PartialEq for E<'a> {
        fn eq(&self, other: &E<'a>) -> bool {
            match (self, other) {
                (E::V(a), E::V(b)) => *a == *b,
            }
        }
    }
}

// Second case: enum contains the reference, equality is desugared
mod second_case {
    pub enum E<'a> {
        V(&'a dyn crate::A),
    }

    impl<'a> ::core::cmp::PartialEq for E<'a> {
        fn eq(&self, other: &E<'a>) -> bool {
            match (self, other) {
                (E::V(a), E::V(b)) => <_ as PartialEq>::eq(&*a, &*b),
            }
        }
    }
}

// Third case: enum contains the `Box`, equality is checked directly
mod third_case {
    pub enum E {
        V(Box<dyn crate::A>),
    }

    impl ::core::cmp::PartialEq for E {
        fn eq(&self, other: &E) -> bool {
            match (self, other) {
                (E::V(a), E::V(b)) => *a == *b,
            }
        }
    }
}

// Fourth case: enum contains the `Box`, equality is desugared
mod fourth_case {
    pub enum E {
        V(Box<dyn crate::A>),
    }

    impl ::core::cmp::PartialEq for E {
        fn eq(&self, other: &E) -> bool {
            match (self, other) {
                (E::V(a), E::V(b)) => <_ as PartialEq>::eq(&*a, &*b),
            }
        }
    }
}

Current output

error: lifetime may not live long enough
  --> src/lib.rs:18:23
   |
15 |     impl<'a> ::core::cmp::PartialEq for E<'a> {
   |          -- lifetime `'a` defined here
...
18 |                 (E::V(a), E::V(b)) => *a == *b,
   |                       ^ assignment requires that `'a` must outlive `'static`

error[E0521]: borrowed data escapes outside of method
  --> src/lib.rs:33:39
   |
30 |     impl<'a> ::core::cmp::PartialEq for E<'a> {
   |          -- lifetime `'a` defined here
31 |         fn eq(&self, other: &E<'a>) -> bool {
   |               ----- `self` is a reference that is only valid in the method body
32 |             match (self, other) {
33 |                 (E::V(a), E::V(b)) => <_ as PartialEq>::eq(&*a, &*b),
   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |                                       |
   |                                       `self` escapes the method body here
   |                                       argument requires that `'a` must outlive `'static`

error[E0507]: cannot move out of `*b` which is behind a shared reference
  --> src/lib.rs:48:45
   |
48 |                 (E::V(a), E::V(b)) => *a == *b,
   |                                             ^^ move occurs because `*b` has type `Box<dyn A>`, which does not implement the `Copy` trait

Desired output

All four cases should probably be treated as the fourth one, i.e. compile without errors.

Rationale and extra context

No response

Other cases

No response

Anything else?

First found on URLO.

@Cerber-Ursi Cerber-Ursi 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 Nov 16, 2023
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Nov 16, 2023
@e2-71828
Copy link

The first and second cases arise from the implicit 'static in the impl PartialEq for dyn A { ... } block. They can be resolved by implementing for all implicit lifetimes instead:

pub trait A {}

impl PartialEq for dyn A + '_ {
    fn eq(&self, _: &Self) -> bool {
        todo!()
    }
}

// First case: enum contains the reference, equality is checked directly
mod first_case {
    pub enum E<'a> {
        V(&'a dyn crate::A),
    }

    impl<'a> ::core::cmp::PartialEq for E<'a> {
        fn eq(&self, other: &E<'a>) -> bool {
            match (self, other) {
                (E::V(a), E::V(b)) => *a == *b,
            }
        }
    }
}

// Second case: enum contains the reference, equality is desugared
mod second_case {
    pub enum E<'a> {
        V(&'a dyn crate::A),
    }

    impl<'a> ::core::cmp::PartialEq for E<'a> {
        fn eq(&self, other: &E<'a>) -> bool {
            match (self, other) {
                (E::V(a), E::V(b)) => <_ as PartialEq>::eq(&*a, &*b),
            }
        }
    }
}

The third case can be further minimized as follows:

pub trait MyTrait {
    fn method(&self);
}

impl PartialEq for dyn MyTrait {
    fn eq(&self, other: &Self) -> bool {
        todo!()
    }
}

fn f1(a: Box<dyn MyTrait>, b:Box<dyn MyTrait>) {
    let _ = (a == b);
    b.method()
}

Which results in the error

error[E0382]: borrow of moved value: `b`
  --> src/lib.rs:13:5
   |
11 | fn f1(a: Box<dyn MyTrait>, b:Box<dyn MyTrait>) {
   |                            - move occurs because `b` has type `Box<dyn MyTrait>`, which does not implement the `Copy` trait
12 |     let _ = (a == b);
   |                   - value moved here
13 |     b.method()
   |     ^ value borrowed here after move

For more information about this error, try `rustc --explain E0382`.

@Cerber-Ursi
Copy link
Contributor Author

quinedot found this to be actually a duplicate of #31740, so closing.

@saethlin saethlin removed the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Nov 18, 2023
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 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

4 participants