哈希特征不适用于枚举中的 Rc<RefCell<T>>

Bin*_* Wu 2 hash enums traits rust refcell

我手动定义一个结构并为其MyData实现PartialEq和特征。Hash

我定义了一个枚举,其中包括Rc<MyData>Rc<RefCell<MyData>>

我想要为枚举导出PartialEqand ,但失败了:Hash

  1. PartialEqHash适用于Rc<MyData>;
  2. 也适用PartialEqRc<RefCell<MyData>>
  3. 但这Hash不起作用Rc<RefCell<MyData>>

我有两个问题:

  1. 为什么?为什么只有Hash不起作用Rc<RefCell<MyData>>

  2. 如何修复它?

    我无法Hash实施Rc<RefCell<MyData>>. 经过搜索后,我找到了一种方法:定义一个新的包装结构,例如struct RRWrapper<T> (Rc<RefCell<T>>),然后实现Hashthis RRWrapper。但这会带来很多代码。有惯用的方法吗?我认为这是一般用法。

预先感谢,

Rc<RefCell<MyData>>PS:在我程序的实际代码中,只有枚举中有,但没有Rc<MyData>。我放在Rc<MyData>这里只是为了比较。Rc<RefCell<T>>PS2:在我的程序的实际代码中,枚举中有多个。


原始源代码:

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() {
}
Run Code Online (Sandbox Code Playgroud)

错误:

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)
Run Code Online (Sandbox Code Playgroud)

源代码struct RRWrapper

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)
Run Code Online (Sandbox Code Playgroud)

Net*_*ave 5

为什么?为什么只有 Hash 不能仅对 Rc<RefCell> 起作用?

如果你仔细想想,这是有道理的,Hash没有实现RefCell. 既然它是内部可变性的抽象,那么可能改变的东西的哈希值可能是什么?一般来说,可变的东西不适合作为Hash对象工作,因此。

如何修复它?

正如你所做的那样。对你真正想要的事情负责。将其实现为包装器。

  • `let s: String` 不是可变的,`let mut s: String` 是可变的。然而,`let r: RefCell&lt;…&gt;` 是可变的,即使它不使用 `let mut`。 (4认同)