Open estebank opened 3 months ago
Interestingly it works if the arguments to f
are Box<dyn Animal>
or &dyn Animal
rather than &Box<dyn Animal>
.
Same issue occurs if the container, in this case RcPtrEq
, implements PartialEq
independently of the dyn
trait object:
#![feature(coerce_unsized)]
#![feature(unsize)]
use std::rc::Rc;
use std::marker::Unsize;
use std::ops::{CoerceUnsized};
pub fn main() {
//#[derive(PartialEq)]
struct Foo {
field: RcPtrEq<dyn Fn()>,
}
// Doesn't compile.
#[automatically_derived]
impl ::core::cmp::PartialEq for Foo {
#[inline]
// error[E0507]: cannot move out of `other.field` which is behind a shared reference
fn eq(&self, other: &Foo) -> bool { self.field == other.field }
}
// Works.
/*
impl PartialEq for Foo {
#[inline]
fn eq(&self, other: &Foo) -> bool { PartialEq::eq(&self.field, &other.field) }
}
*/
}
pub struct RcPtrEq<T: ?Sized>(Rc<T>);
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<RcPtrEq<U>> for RcPtrEq<T> {}
impl<T: ?Sized> PartialEq for RcPtrEq<T> {
fn eq(&self, other: &Self) -> bool {
Rc::ptr_eq(&self.0, &other.0)
}
}
Strangely, removing CoercedUnized
makes it compile.
This also breaks the PartialEq derive macro when used on structs.
use std::rc::Rc;
trait Trait {}
impl PartialEq for dyn Trait {
fn eq(&self, _: &Self) -> bool { todo!() }
}
#[derive(PartialEq)]
struct User(Rc<dyn Trait>);
The following code produces a move error:
But according to the reference, it should be equivalent to the following, which does work:
It seems to be specific to trait objects; e.g. replacing
Box<dyn Animal>
withBox<[String]>
will make both versions off
compile.Originally reported in https://github.com/rust-lang/rust/issues/123056#issuecomment-2067785879