How to look up element through chained borrows?

I'm trying to look up an element from a HashSet<Box<T>> given a &Q where T: Borrow<Q>. If I had a HashSet<T> I could use get with no problem. But just putting the T in a Box seems to make this impossible.

As you can guess, there are more constraints, and I'm trying to enable an interface somewhat like that of HashSet::get. I could change the pointer type that is in the HashSet, but can't put the T in there directly, because I need the location of the value in memory to be stable. This is for an improvement to my internment crate.

Any suggestions?

The raw_entry API helps:

#![feature(hash_raw_entry)]

use std::collections::HashMap;
use std::{
    borrow::Borrow,
    hash::{BuildHasher, Hash, Hasher},
};

pub fn get<T: Borrow<Q>, Q: ?Sized + Eq + Hash, V: Clone>(
    map: &HashMap<Box<T>, V>,
    key: &Q,
) -> Option<V> {
    let hash = {
        let mut hasher = map.hasher().build_hasher();
        key.hash(&mut hasher);
        hasher.finish()
    };
    map.raw_entry()
        .from_hash(hash, |k| <T as Borrow<Q>>::borrow(k) == key)
        .as_ref()
        .map(|kv| kv.1.clone())
}
  • You have to use HashMap<K, ()> instead of HashSet<K>
  • It is Nightly only. Alternatively, hashbrown exposes the same API with a feature flag and it can be used in the stable Rust.

Thanks, I think that does what I'm looking for!

Modified to return the key rather than the value, it looks like [playground] (https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=a6d1677c9c62972c5a714562da986ae3).

I wish I saw a way to abstract this such that I could make a nice set with any type of pointer entry.

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.