X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=compiler%2Frustc_data_structures%2Fsrc%2Funord.rs;h=f35f18e51cb4e5339dfd8a4b88b9c291ce773256;hb=d667105681726fe84ef6256b8a75b2e770bed3e6;hp=14257e4d5c60b8c1ccbd5c40b89267b0162d19eb;hpb=ed77ffe166506422f208f3a3870e77893ae84449;p=rust.git diff --git a/compiler/rustc_data_structures/src/unord.rs b/compiler/rustc_data_structures/src/unord.rs index 14257e4d5c6..f35f18e51cb 100644 --- a/compiler/rustc_data_structures/src/unord.rs +++ b/compiler/rustc_data_structures/src/unord.rs @@ -6,13 +6,15 @@ use smallvec::SmallVec; use std::{ borrow::Borrow, + collections::hash_map::Entry, hash::Hash, iter::{Product, Sum}, + ops::Index, }; use crate::{ fingerprint::Fingerprint, - stable_hasher::{HashStable, StableHasher, ToStableHashKey}, + stable_hasher::{HashStable, StableHasher, StableOrd, ToStableHashKey}, }; /// `UnordItems` is the order-less version of `Iterator`. It only contains methods @@ -38,17 +40,17 @@ pub fn map U>(self, f: F) -> UnordItems bool>(mut self, f: F) -> bool { + pub fn all bool>(mut self, f: F) -> bool { self.0.all(f) } #[inline] - pub fn any bool>(mut self, f: F) -> bool { + pub fn any bool>(mut self, f: F) -> bool { self.0.any(f) } #[inline] - pub fn filter bool>(self, f: F) -> UnordItems> { + pub fn filter bool>(self, f: F) -> UnordItems> { UnordItems(self.0.filter(f)) } @@ -96,6 +98,15 @@ pub fn product(self) -> S pub fn count(self) -> usize { self.0.count() } + + #[inline] + pub fn flat_map(self, f: F) -> UnordItems> + where + U: IntoIterator, + F: Fn(T) -> U, + { + UnordItems(self.0.flat_map(f)) + } } impl<'a, T: Clone + 'a, I: Iterator> UnordItems<&'a T, I> { @@ -147,6 +158,7 @@ pub struct UnordSet { } impl Default for UnordSet { + #[inline] fn default() -> Self { Self { inner: FxHashSet::default() } } @@ -178,7 +190,16 @@ pub fn contains(&self, v: &Q) -> bool } #[inline] - pub fn items(&self) -> UnordItems<&V, impl Iterator> { + pub fn remove(&mut self, k: &Q) -> bool + where + V: Borrow, + Q: Hash + Eq, + { + self.inner.remove(k) + } + + #[inline] + pub fn items<'a>(&'a self) -> UnordItems<&'a V, impl Iterator> { UnordItems(self.inner.iter()) } @@ -187,20 +208,75 @@ pub fn into_items(self) -> UnordItems> { UnordItems(self.inner.into_iter()) } + /// Returns the items of this set in stable sort order (as defined by `ToStableHashKey`). + /// + /// The `cache_sort_key` parameter controls if [slice::sort_by_cached_key] or + /// [slice::sort_unstable_by_key] will be used for sorting the vec. Use + /// `cache_sort_key` when the [ToStableHashKey::to_stable_hash_key] implementation + /// for `V` is expensive (e.g. a `DefId -> DefPathHash` lookup). + #[inline] + pub fn to_sorted(&self, hcx: &HCX, cache_sort_key: bool) -> Vec<&V> + where + V: ToStableHashKey, + { + to_sorted_vec(hcx, self.inner.iter(), cache_sort_key, |&x| x) + } + + /// Returns the items of this set in stable sort order (as defined by + /// `StableOrd`). This method is much more efficient than + /// `into_sorted` because it does not need to transform keys to their + /// `ToStableHashKey` equivalent. + #[inline] + pub fn to_sorted_stable_ord(&self) -> Vec + where + V: Ord + StableOrd + Copy, + { + let mut items: Vec = self.inner.iter().copied().collect(); + items.sort_unstable(); + items + } + + /// Returns the items of this set in stable sort order (as defined by `ToStableHashKey`). + /// + /// The `cache_sort_key` parameter controls if [slice::sort_by_cached_key] or + /// [slice::sort_unstable_by_key] will be used for sorting the vec. Use + /// `cache_sort_key` when the [ToStableHashKey::to_stable_hash_key] implementation + /// for `V` is expensive (e.g. a `DefId -> DefPathHash` lookup). + #[inline] + pub fn into_sorted(self, hcx: &HCX, cache_sort_key: bool) -> Vec + where + V: ToStableHashKey, + { + to_sorted_vec(hcx, self.inner.into_iter(), cache_sort_key, |x| x) + } + // We can safely extend this UnordSet from a set of unordered values because that // won't expose the internal ordering anywhere. #[inline] pub fn extend>(&mut self, items: UnordItems) { self.inner.extend(items.0) } + + #[inline] + pub fn clear(&mut self) { + self.inner.clear(); + } } impl Extend for UnordSet { + #[inline] fn extend>(&mut self, iter: T) { self.inner.extend(iter) } } +impl FromIterator for UnordSet { + #[inline] + fn from_iter>(iter: T) -> Self { + UnordSet { inner: FxHashSet::from_iter(iter) } + } +} + impl> HashStable for UnordSet { #[inline] fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { @@ -223,17 +299,33 @@ pub struct UnordMap { } impl Default for UnordMap { + #[inline] fn default() -> Self { Self { inner: FxHashMap::default() } } } impl Extend<(K, V)> for UnordMap { + #[inline] fn extend>(&mut self, iter: T) { self.inner.extend(iter) } } +impl FromIterator<(K, V)> for UnordMap { + #[inline] + fn from_iter>(iter: T) -> Self { + UnordMap { inner: FxHashMap::from_iter(iter) } + } +} + +impl> From> for UnordMap { + #[inline] + fn from(items: UnordItems<(K, V), I>) -> Self { + UnordMap { inner: FxHashMap::from_iter(items.0) } + } +} + impl UnordMap { #[inline] pub fn len(&self) -> usize { @@ -255,7 +347,44 @@ pub fn contains_key(&self, k: &Q) -> bool } #[inline] - pub fn items(&self) -> UnordItems<(&K, &V), impl Iterator> { + pub fn is_empty(&self) -> bool { + self.inner.is_empty() + } + + #[inline] + pub fn entry(&mut self, key: K) -> Entry<'_, K, V> { + self.inner.entry(key) + } + + #[inline] + pub fn get(&self, k: &Q) -> Option<&V> + where + K: Borrow, + Q: Hash + Eq, + { + self.inner.get(k) + } + + #[inline] + pub fn get_mut(&mut self, k: &Q) -> Option<&mut V> + where + K: Borrow, + Q: Hash + Eq, + { + self.inner.get_mut(k) + } + + #[inline] + pub fn remove(&mut self, k: &Q) -> Option + where + K: Borrow, + Q: Hash + Eq, + { + self.inner.remove(k) + } + + #[inline] + pub fn items<'a>(&'a self) -> UnordItems<(&'a K, &'a V), impl Iterator> { UnordItems(self.inner.iter()) } @@ -270,6 +399,77 @@ pub fn into_items(self) -> UnordItems<(K, V), impl Iterator> { pub fn extend>(&mut self, items: UnordItems<(K, V), I>) { self.inner.extend(items.0) } + + /// Returns the entries of this map in stable sort order (as defined by `ToStableHashKey`). + /// + /// The `cache_sort_key` parameter controls if [slice::sort_by_cached_key] or + /// [slice::sort_unstable_by_key] will be used for sorting the vec. Use + /// `cache_sort_key` when the [ToStableHashKey::to_stable_hash_key] implementation + /// for `K` is expensive (e.g. a `DefId -> DefPathHash` lookup). + #[inline] + pub fn to_sorted(&self, hcx: &HCX, cache_sort_key: bool) -> Vec<(&K, &V)> + where + K: ToStableHashKey, + { + to_sorted_vec(hcx, self.inner.iter(), cache_sort_key, |&(k, _)| k) + } + + /// Returns the entries of this map in stable sort order (as defined by `StableOrd`). + /// This method can be much more efficient than `into_sorted` because it does not need + /// to transform keys to their `ToStableHashKey` equivalent. + #[inline] + pub fn to_sorted_stable_ord(&self) -> Vec<(K, &V)> + where + K: Ord + StableOrd + Copy, + { + let mut items: Vec<(K, &V)> = self.inner.iter().map(|(&k, v)| (k, v)).collect(); + items.sort_unstable_by_key(|&(k, _)| k); + items + } + + /// Returns the entries of this map in stable sort order (as defined by `ToStableHashKey`). + /// + /// The `cache_sort_key` parameter controls if [slice::sort_by_cached_key] or + /// [slice::sort_unstable_by_key] will be used for sorting the vec. Use + /// `cache_sort_key` when the [ToStableHashKey::to_stable_hash_key] implementation + /// for `K` is expensive (e.g. a `DefId -> DefPathHash` lookup). + #[inline] + pub fn into_sorted(self, hcx: &HCX, cache_sort_key: bool) -> Vec<(K, V)> + where + K: ToStableHashKey, + { + to_sorted_vec(hcx, self.inner.into_iter(), cache_sort_key, |(k, _)| k) + } + + /// Returns the values of this map in stable sort order (as defined by K's + /// `ToStableHashKey` implementation). + /// + /// The `cache_sort_key` parameter controls if [slice::sort_by_cached_key] or + /// [slice::sort_unstable_by_key] will be used for sorting the vec. Use + /// `cache_sort_key` when the [ToStableHashKey::to_stable_hash_key] implementation + /// for `K` is expensive (e.g. a `DefId -> DefPathHash` lookup). + #[inline] + pub fn values_sorted(&self, hcx: &HCX, cache_sort_key: bool) -> impl Iterator + where + K: ToStableHashKey, + { + to_sorted_vec(hcx, self.inner.iter(), cache_sort_key, |&(k, _)| k) + .into_iter() + .map(|(_, v)| v) + } +} + +impl Index<&Q> for UnordMap +where + K: Eq + Hash + Borrow, + Q: Eq + Hash, +{ + type Output = V; + + #[inline] + fn index(&self, key: &Q) -> &V { + &self.inner[key] + } } impl, V: HashStable> HashStable for UnordMap { @@ -334,6 +534,12 @@ fn extend>(&mut self, iter: I) { } } +impl> From> for UnordBag { + fn from(value: UnordItems) -> Self { + UnordBag { inner: Vec::from_iter(value.0) } + } +} + impl> HashStable for UnordBag { #[inline] fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { @@ -341,6 +547,27 @@ fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) { } } +#[inline] +fn to_sorted_vec( + hcx: &HCX, + iter: I, + cache_sort_key: bool, + extract_key: fn(&T) -> &K, +) -> Vec +where + I: Iterator, + K: ToStableHashKey, +{ + let mut items: Vec = iter.collect(); + if cache_sort_key { + items.sort_by_cached_key(|x| extract_key(x).to_stable_hash_key(hcx)); + } else { + items.sort_unstable_by_key(|x| extract_key(x).to_stable_hash_key(hcx)); + } + + items +} + fn hash_iter_order_independent< HCX, T: HashStable,