I define a struct MyData
and implement PartialEq
and Hash
traits for it manually.
I define a enum which includes Rc<MyData>
and Rc<RefCell<MyData>>
.
I want derive PartialEq
and Hash
for the enum, but fails:
- The
PartialEq
andHash
both work forRc<MyData>
; - The
PartialEq
works forRc<RefCell<MyData>>
too; - But the
Hash
does not work forRc<RefCell<MyData>>
!
I have 2 questions:
Why? Why only the
Hash
does not work only forRc<RefCell<MyData>>
?How to fix it?
I can not implement
Hash
forRc<RefCell<MyData>>
. After searching around I find a way: defining a new wrapper struct, likestruct RRWrapper<T> (Rc<RefCell<T>>)
, and then implementHash
for thisRRWrapper
. But this will bring much code. Is there an idiomatic way? I think this's a general usage.
Thank in advance,
Wu
PS: In the real code of my program, there is only Rc<RefCell<MyData>>
in the enum but no Rc<MyData>
. I put Rc<MyData>
here just for comparision.
PS2: In the real code of my program, there are more than one Rc<RefCell<T>>
in the enum.
Original source code:
use std::rc::Rc;
use std::cell::RefCell;
use std::hash::{Hash, Hasher};
struct MyData {
i: i64,
}
impl Hash for MyData {
fn hash<H: Hasher>(&self, state: &mut H) {
self.hash(state);
}
}
impl PartialEq for MyData {
fn eq(&self, other: &Self) -> bool {
self == other
}
}
#[derive(PartialEq, Hash)]
enum MyEnum {
INT(i64),
STR(String),
MYDATA1(Rc<MyData>), // OK both
MYDATA2(Rc<RefCell<MyData>>), // OK for PartialEq but not for Hash
}
fn main() {
}
Error:
20 | #[derive(PartialEq, Hash)]
| ---- in this derive macro expansion
...
25 | MYDATA2(Rc<RefCell<MyData>>), // OK for PartialEq but not for Hash
| ^^^^^^^^^^^^^^^^^^^ the trait `Hash` is not implemented for `RefCell<MyData>`
|
= note: required because of the requirements on the impl of `Hash` for `Rc<RefCell<MyData>>`
= note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
Source code of struct RRWrapper
:
#[derive(Debug, PartialEq, Eq)]
pub struct RRWrapper<T: Hash+PartialEq+Eq>(Rc<RefCell<T>>);
impl<T: Hash+PartialEq+Eq> Deref for RRWrapper<T> {
type Target = Rc<RefCell<T>>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: Hash+PartialEq+Eq> Hash for RRWrapper<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.borrow().hash(state);
}
}
impl<T: Hash+PartialEq+Eq> Clone for RRWrapper<T> {
fn clone(&self) -> Self {
RRWrapper(self.0.clone())
}
}
impl<T: Hash+PartialEq+Eq> RRWrapper<T> {
pub fn new(inner: T) -> Self {
RRWrapper(Rc::new(RefCell::new(inner)))
}
}