Impl Hash for RwLock like serde impls Serialize for RwLock

I need to implement Hash for RwLock.
I tried the following :

impl Hash for RwLock<MathExpression> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.read().unwrap().deref().hash(state);
    }
}

And got

error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
 --> src/engine/mod.rs:8:1
  |
8 | impl Hash for RwLock<MathExpression> {
  | ^^^^^^^^^^^^^^----------------------
  | |             |
  | |             `RwLock` is not defined in the current crate
  | impl doesn't use only types from inside the current crate
  |
  = note: define and implement a trait or new type instead

I then tried

#[cfg(feature = "std")]
impl Hash for RwLock<MathExpression> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.read().unwrap().deref().hash(state);
    }
}

(like I saw in serde's source code)
and got

error[E0277]: the trait bound `RwLock<MathExpression>: Hash` is not satisfied
   --> src/engine/mod.rs:36:49
    |
36  |     Fraction {nom: Arc<RwLock<MathExpression>>, denom: Arc<RwLock<MathExpression>>}
    |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Hash` is not implemented for `RwLock<MathExpression>`
    | 
   ::: /home/teln0/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/hash/mod.rs:168:13
    |
168 |     fn hash<H: Hasher>(&self, state: &mut H);
    |             - required by this bound in `std::hash::Hash::hash`
    |
    = note: required because of the requirements on the impl of `Hash` for `Arc<RwLock<MathExpression>>`
    = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)

I'm sure there is an easy fix for this but I don't know what it is...

Tried that, doesn't work as well

trait HashWrapper {
    fn hash_wp<H: Hasher>(&self, state: &mut H);
}

impl HashWrapper for RwLock<MathExpression> {
    fn hash_wp<H: Hasher>(&self, state: &mut H) {
        self.read().unwrap().deref().hash(state);
    }
}

impl<T: HashWrapper> Hash for T {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.hash_wp()
    }
}

Because something something downstream crates even if HashWrapper isn't public

Sadly you can't do that. Instead, you need to manually impl Hash for your own type containing the RwLock. If such type is "too big", you can use an intermediate newtype wrapper:

struct HashRwLock<T : ?Sized> /* = */ (
    RwLock<T>,
);

impl<T : ?Sized + Hash> Hash for HashRwLock<T> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.0.read().unwrap().deref().hash(state);
    }
}

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.