-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
"cannot move out of" error using ==
with Box<Trait>
, where no move is needed
#31740
Comments
Doing |
When comparing two different boxes, the equality operation does take ownership of the second one, even though that's plainly impossible from the signature of |
This does not only occur for the reflexive case. See https://is.gd/MWU7Kw
|
I'm not sure what the difference is. I based that (“This only occurs for the reflexive (x == x) case”) on that this compiles: trait Trait { }
impl<T> Trait for T { }
impl<'a> PartialEq for Trait + 'a {
fn eq(&self, other: &Self) -> bool { false }
}
fn main() {
let x = Box::new(1) as Box<Trait>;
let y = Box::new(1) as Box<Trait>;
let equal = x == y;
} |
Ah, with durka's explanation it is clear. |
@bluss but it moves |
@bluss try adding another identical |
Triage: no change |
Just got this recently. Had asked on Stack Overflow, vikrrrr and zuurr figured out what was going on at a lower level. https://stackoverflow.com/questions/56050864/cannot-move-out-of-an-rc Here's the generated PartialEq for my example:
|
I encountered this yesterday and was quite confused by it for a while. I wonder if this issue also occurs with the other comparison operators? I'd written a new issue report for it today because the issue searcher wasn't finding this issue #31740 for me until I entered a title for my issue, so I may as well add what I boiled down my case to: trait Mine {}
impl Mine for i32 {}
impl PartialEq for dyn Mine {
fn eq(&self, _other: &dyn Mine) -> bool {
true
}
}
fn main() {
let b1: Box<dyn Mine> = Box::new(1);
let b2: Box<dyn Mine> = Box::new(1);
if b1 == b2 {}
if b1 == b2 {}
}
The following alternative form that is supposed to be equivalent (IIUC) works: let b1r: &Box<dyn Mine> = &b1;
let b2r: &Box<dyn Mine> = &b2;
if <Box<dyn Mine> as PartialEq>::eq(b1r, b2r) {}
if <Box<dyn Mine> as PartialEq>::eq(b1r, b2r) {} |
#75231 has a new example with 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 ran into this bug when trying to auto-derive pub trait Trait {}
/* This impl is not sufficient and causes "the cannot move out of `*__self_1_0` which is behind a shared reference" error. */
impl PartialEq for Box<dyn Trait> {
fn eq(&self, _other: &Self) -> bool {
todo!();
}
}
/* Code fails to compile without this impl. */
impl PartialEq<&Self> for Box<dyn Trait> {
fn eq(&self, _other: &&Self) -> bool {
todo!();
}
}
#[derive(PartialEq)]
struct Foo {
x: Box<dyn Trait>
} |
See this example (also try macro expansion). It's based on @bluss's one. It gives us the following:
|
Not only |
Here is a repro using a custom type (playground): #![feature(coerce_unsized, unsize)]
use core::{marker::Unsize, ops::CoerceUnsized};
struct Foo<T: ?Sized>(*const T);
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Foo<U>> for Foo<T> {}
impl<T: ?Sized + PartialEq> PartialEq for Foo<T> {
fn eq(&self, _: &Self) -> bool { loop {} }
}
trait Trait {}
impl PartialEq for dyn Trait {
fn eq(&self, _: &Self) -> bool { loop {} }
}
fn test(x: Foo<dyn Trait>, y: Foo<dyn Trait>) {
x == y;
drop(y);
} Note line 6, the implementation of The strange thing is that no unsized coercion is necessary here (albeit they must probably be used elsewhere in order to obtain instances of Interestingly, if the
So it looks like the comparison operators are attempting to coerce from one unsized type (with |
I ran into this bug the other day but failed to discover this thread while trying to figure it out, so I ended up asking about it on StackOverflow. Now that I know about the bug and have already created a repro and SO question, I figured that I should add it to the set of examples: Why does the equality operator for owned trait object move the right operand? |
The following code has a compilation error, but it should be a valid program (playground)
(Updated code in 2021 edition)
x == y
.Box<[T]>
don't behave like thisThe error is the same when using this equality impl instead:
The text was updated successfully, but these errors were encountered: