]> git.lizzy.rs Git - rust.git/blob - src/librustc_data_structures/interner.rs
Auto merge of #59445 - alexreg:ban-multi-trait-objects-via-aliases, r=oli-obk
[rust.git] / src / librustc_data_structures / interner.rs
1 use std::hash::Hash;
2 use std::hash::BuildHasher;
3 use std::hash::Hasher;
4 use std::collections::HashMap;
5 use std::collections::hash_map::RawEntryMut;
6 use std::borrow::Borrow;
7
8 pub trait HashInterner<K: Eq + Hash> {
9     fn intern_ref<Q: ?Sized, F: FnOnce() -> K>(&mut self, value: &Q, make: F) -> K
10         where K: Borrow<Q>,
11               Q: Hash + Eq;
12
13     fn intern<Q, F: FnOnce(Q) -> K>(&mut self, value: Q, make: F) -> K
14         where K: Borrow<Q>,
15               Q: Hash + Eq;
16 }
17
18 impl<K: Eq + Hash + Copy, S: BuildHasher> HashInterner<K> for HashMap<K, (), S> {
19     #[inline]
20     fn intern_ref<Q: ?Sized, F: FnOnce() -> K>(&mut self, value: &Q, make: F) -> K
21         where K: Borrow<Q>,
22               Q: Hash + Eq
23     {
24         let mut hasher = self.hasher().build_hasher();
25         value.hash(&mut hasher);
26         let hash = hasher.finish();
27         let entry = self.raw_entry_mut().from_key_hashed_nocheck(hash, value);
28
29         match entry {
30             RawEntryMut::Occupied(e) => *e.key(),
31             RawEntryMut::Vacant(e) => {
32                 let v = make();
33                 e.insert_hashed_nocheck(hash, v, ());
34                 v
35             }
36         }
37     }
38
39     #[inline]
40     fn intern<Q, F: FnOnce(Q) -> K>(&mut self, value: Q, make: F) -> K
41         where K: Borrow<Q>,
42               Q: Hash + Eq
43     {
44         let mut hasher = self.hasher().build_hasher();
45         value.hash(&mut hasher);
46         let hash = hasher.finish();
47         let entry = self.raw_entry_mut().from_key_hashed_nocheck(hash, &value);
48
49         match entry {
50             RawEntryMut::Occupied(e) => *e.key(),
51             RawEntryMut::Vacant(e) => {
52                 let v = make(value);
53                 e.insert_hashed_nocheck(hash, v, ());
54                 v
55             }
56         }
57     }
58 }