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

*a == *b moves when dereferencing &Rc<RefCell<dyn Trait>> #75231

Closed
cuviper opened this issue Aug 6, 2020 · 2 comments
Closed

*a == *b moves when dereferencing &Rc<RefCell<dyn Trait>> #75231

cuviper opened this issue Aug 6, 2020 · 2 comments
Labels
C-bug Category: This is a bug.

Comments

@cuviper
Copy link
Member

cuviper commented Aug 6, 2020

This bug report comes from a question in the users forum:
https://users.rust-lang.org/t/attempting-to-contain-an-rc-refcell-sometrait-in-an-enum-field-with-clone/46913

They had a problem with #[derive(PartialEq)] on an enum where one variant contains Rc<RefCell<dyn Trait>>, and there is a manual PartialEq for that dyn Trait. I looked at the macro expansion to see that it matches ref patterns and then uses (*__self_0) == (*__arg_1_0), so I reduced the error to this code:

use std::cell::RefCell;
use std::rc::Rc;

pub trait Trait {}

impl PartialEq<dyn Trait> for dyn Trait {
    fn eq(&self, _other: &Self) -> bool {
        todo!();
    }
}

pub fn eq(a: &Rc<RefCell<dyn Trait>>, b: &Rc<RefCell<dyn Trait>>) -> bool {
    *a == *b
}

I expected to see this happen: successful compilation

Instead, this happened: (playground)

error[E0507]: cannot move out of `*b` which is behind a shared reference
  --> src/lib.rs:13:11
   |
13 |     *a == *b
   |           ^^ move occurs because `*b` has type `std::rc::Rc<std::cell::RefCell<dyn Trait>>`, which does not implement the `Copy` trait

Meta

The error is the same with all compilers currently on the playground, 1.45.2, 1.46.0-beta.2, and 1.47.0-nightly (2020-08-05 22ee68dc586440f96b76).

Reduction

Changing to a == b works, but that's not helpful when we want the derived code to work.

Reducing the parameters to &RefCell<dyn Trait> does build successfully.

Reducing the parameters to &dyn Trait changes to a lifetime error:

error[E0621]: explicit lifetime required in the type of `a`
  --> src/lib.rs:13:8
   |
12 | pub fn eq(a: &dyn Trait, b: &dyn Trait) -> bool {
   |              ---------- help: add explicit lifetime `'static` to the type of `a`: `&'static (dyn Trait + 'static)`
13 |     *a == *b
   |        ^^ lifetime `'static` required

error[E0621]: explicit lifetime required in the type of `b`
  --> src/lib.rs:13:11
   |
12 | pub fn eq(a: &dyn Trait, b: &dyn Trait) -> bool {
   |                             ---------- help: add explicit lifetime `'static` to the type of `b`: `&'static (dyn Trait + 'static)`
13 |     *a == *b
   |           ^^ lifetime `'static` required

This one is solved by changing to 'static as suggested, or by changing the PartialEq to:

impl<'a> PartialEq<dyn Trait + 'a> for dyn Trait + 'a { ... }
// or even
impl<'a, 'b> PartialEq<dyn Trait + 'b> for dyn Trait + 'a { ... }

... but that change does nothing for the original issue.

@cuviper cuviper added the C-bug Category: This is a bug. label Aug 6, 2020
@lcnr
Copy link
Contributor

lcnr commented Aug 7, 2020

Is this a duplicate of #31740?

@cuviper
Copy link
Member Author

cuviper commented Aug 7, 2020

I suppose it is a dupe, or at least close enough that it's probably the same root cause. The context is a little different here, since it came up as part of a derived implementation, which makes it even more troublesome.

BTW, changing the parameters to &Rc<dyn Trait> also fails the same way, so I guess that's a further reduction. Same for &Box<dyn Trait>, more like #31740, but it may be important to remember that this doesn't only affect Box.

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.
Projects
None yet
Development

No branches or pull requests

2 participants