0
votes

I'm trying to clone a HashMap<Weak, Weak> as a HashMap<Rc, Rc>:

type RcCell<T> = Rc<RefCell<T>>;
type WeakCell<T> = Weak<RefCell<T>>;

type SymbolRef = RcCell<Symbol>;
type WeakSymbolRef = WeakCell<Symbol>;

struct S {
    _some_list: Option<HashMap<WeakSymbolRef, WeakSymbolRef>>,
}

impl Symbol for RcCell<S> {
    fn some_list(&self) -> HashMap<SymbolRef, SymbolRef> {
        if let Some(ls) = self.borrow()._some_list {
            ls.iter().map(|(k, v)| (k.upgrade().unwrap(), v.upgrade().unwrap())).collect()
        } else {
            HashMap::new()
        }
    }
}

collect() fails with:

the trait bound std::cell::RefCell<(dyn symbols::Symbol + 'static)>: std::hash::Hash is not satisfied

the trait std::hash::Hash is not implemented for std::cell::RefCell<(dyn symbols::Symbol + 'static)>

I'm expecting for Rc to use its internal pointer for hashing in this case. Is there an alternative to iter().map().collect()? Or is there an alternative for HashMap?

Based on users.rust-lang.org, I tried to implement Hash for SymbolRef:

use std::hash::{Hash, Hasher};

impl Hash for SymbolRef {
    fn hash<H: Hasher>(&self, state: &mut H) {
        std::ptr::hash(&**self, state)
    }
}

But Rustc complains:

conflicting implementations of trait std::hash::Hash for type std::rc::Rc<std::cell::RefCell<(dyn symbols::Symbol + 'static)>>

How do you think you will be able to populate _some_list in the first place?trentcl
@trentcl That's possible through self.borrow_mut()._some_list.unwrap().push(...);..Klaider
@trentcl Oops, instead of push() I meant insert().Klaider
insert also requires K: Hash, which means you must solve the same problem you are asking about here. (Also you will need to use Option::as_ref to make unwrap work)trentcl
In any case, I'm not completely sure what you mean by "expecting Rc to use its internal pointer for hashing" -- do you mean you expect it to hash the pointed-to value, or hash the pointer itself? Either one is possible, but has drawbacks.trentcl