trait A : {
fn as_u64(&self) -> u64;
}
impl A for u64 {
fn as_u64(&self) -> u64 {
*self
}
}
impl PartialEq for Box<dyn A> {
fn eq(&self, other: &Self) -> bool {
self.as_u64() == other.as_u64()
}
}
fn main() {
let p1: Box<dyn A> = Box::new(21);
let p2: Box<dyn A> = Box::new(22);
let p3: Box<dyn A> = Box::new(21);
assert!(p1 != p2);
assert!(p3 != p2);
assert!(p1 == p3);
}
Error produced:
Compiling playground v0.0.1 (/playground)
error[E0382]: use of moved value: `p2`
--> src/main.rs:22:19
|
19 | let p2: Box<dyn A> = Box::new(22);
| -- move occurs because `p2` has type `Box<dyn A>`, which does not implement the `Copy` trait
20 | let p3: Box<dyn A> = Box::new(21);
21 | assert!(p1 != p2);
| -- value moved here
22 | assert!(p3 != p2);
| ^^ value used here after move
For more information about this error, try `rustc --explain E0382`.
error: could not compile `playground` (bin "playground") due to 1 previous error
But if I change assert!(p1 != p2) to assert!(p1.ne(&p2));, it compiles and runs fine, without errors. assert!(&p1 != &p2); works fine too, but clippy throws a message asking me to use assert!(p1 != p2) which doesn't compile.
From what I understand, != should be synonymous with using ne, so am I missing something here?
Interesting. It seems you have found a compiler/language bug. Normally, the == and != operators implicitly borrow their arguments, but in the particular case of Box<dyn Trait> something else happens. This seems to be the relevant issue:
I guess in real code there is Box<dyn Trait> coming from somewhere else, where it has to be a trait object. In your code, every variable will be Box<{integer}>, not Box<dyn A>.
Funny thing that people do not understand that safety != logically correct. For example, when I did a testing of the example and slightly modified the implementation to be sure that a correct function called:
impl PartialEq for Box<dyn A> {
fn eq(&self, other: &Self) -> bool {
(self.as_u64() + 1) == other.as_u64()
}
}