• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! This module contains collection types that don't expose their internal
2 //! ordering. This is a useful property for deterministic computations, such
3 //! as required by the query system.
4 
5 use rustc_hash::{FxHashMap, FxHashSet};
6 use smallvec::SmallVec;
7 use std::{
8     borrow::Borrow,
9     collections::hash_map::Entry,
10     hash::Hash,
11     iter::{Product, Sum},
12     ops::Index,
13 };
14 
15 use crate::{
16     fingerprint::Fingerprint,
17     stable_hasher::{HashStable, StableHasher, StableOrd, ToStableHashKey},
18 };
19 
20 /// `UnordItems` is the order-less version of `Iterator`. It only contains methods
21 /// that don't (easily) expose an ordering of the underlying items.
22 ///
23 /// Most methods take an `Fn` where the `Iterator`-version takes an `FnMut`. This
24 /// is to reduce the risk of accidentally leaking the internal order via the closure
25 /// environment. Otherwise one could easily do something like
26 ///
27 /// ```rust,ignore (pseudo code)
28 /// let mut ordered = vec![];
29 /// unordered_items.all(|x| ordered.push(x));
30 /// ```
31 ///
32 /// It's still possible to do the same thing with an `Fn` by using interior mutability,
33 /// but the chance of doing it accidentally is reduced.
34 pub struct UnordItems<T, I: Iterator<Item = T>>(I);
35 
36 impl<T, I: Iterator<Item = T>> UnordItems<T, I> {
37     #[inline]
map<U, F: Fn(T) -> U>(self, f: F) -> UnordItems<U, impl Iterator<Item = U>>38     pub fn map<U, F: Fn(T) -> U>(self, f: F) -> UnordItems<U, impl Iterator<Item = U>> {
39         UnordItems(self.0.map(f))
40     }
41 
42     #[inline]
all<F: Fn(T) -> bool>(mut self, f: F) -> bool43     pub fn all<F: Fn(T) -> bool>(mut self, f: F) -> bool {
44         self.0.all(f)
45     }
46 
47     #[inline]
any<F: Fn(T) -> bool>(mut self, f: F) -> bool48     pub fn any<F: Fn(T) -> bool>(mut self, f: F) -> bool {
49         self.0.any(f)
50     }
51 
52     #[inline]
filter<F: Fn(&T) -> bool>(self, f: F) -> UnordItems<T, impl Iterator<Item = T>>53     pub fn filter<F: Fn(&T) -> bool>(self, f: F) -> UnordItems<T, impl Iterator<Item = T>> {
54         UnordItems(self.0.filter(f))
55     }
56 
57     #[inline]
filter_map<U, F: Fn(T) -> Option<U>>( self, f: F, ) -> UnordItems<U, impl Iterator<Item = U>>58     pub fn filter_map<U, F: Fn(T) -> Option<U>>(
59         self,
60         f: F,
61     ) -> UnordItems<U, impl Iterator<Item = U>> {
62         UnordItems(self.0.filter_map(f))
63     }
64 
65     #[inline]
max(self) -> Option<T> where T: Ord,66     pub fn max(self) -> Option<T>
67     where
68         T: Ord,
69     {
70         self.0.max()
71     }
72 
73     #[inline]
min(self) -> Option<T> where T: Ord,74     pub fn min(self) -> Option<T>
75     where
76         T: Ord,
77     {
78         self.0.min()
79     }
80 
81     #[inline]
sum<S>(self) -> S where S: Sum<T>,82     pub fn sum<S>(self) -> S
83     where
84         S: Sum<T>,
85     {
86         self.0.sum()
87     }
88 
89     #[inline]
product<S>(self) -> S where S: Product<T>,90     pub fn product<S>(self) -> S
91     where
92         S: Product<T>,
93     {
94         self.0.product()
95     }
96 
97     #[inline]
count(self) -> usize98     pub fn count(self) -> usize {
99         self.0.count()
100     }
101 
102     #[inline]
flat_map<U, F, O>(self, f: F) -> UnordItems<O, impl Iterator<Item = O>> where U: IntoIterator<Item = O>, F: Fn(T) -> U,103     pub fn flat_map<U, F, O>(self, f: F) -> UnordItems<O, impl Iterator<Item = O>>
104     where
105         U: IntoIterator<Item = O>,
106         F: Fn(T) -> U,
107     {
108         UnordItems(self.0.flat_map(f))
109     }
110 
collect<C: From<UnordItems<T, I>>>(self) -> C111     pub fn collect<C: From<UnordItems<T, I>>>(self) -> C {
112         self.into()
113     }
114 }
115 
116 impl<T> UnordItems<T, std::iter::Empty<T>> {
empty() -> Self117     pub fn empty() -> Self {
118         UnordItems(std::iter::empty())
119     }
120 }
121 
122 impl<'a, T: Clone + 'a, I: Iterator<Item = &'a T>> UnordItems<&'a T, I> {
123     #[inline]
cloned(self) -> UnordItems<T, impl Iterator<Item = T>>124     pub fn cloned(self) -> UnordItems<T, impl Iterator<Item = T>> {
125         UnordItems(self.0.cloned())
126     }
127 }
128 
129 impl<'a, T: Copy + 'a, I: Iterator<Item = &'a T>> UnordItems<&'a T, I> {
130     #[inline]
copied(self) -> UnordItems<T, impl Iterator<Item = T>>131     pub fn copied(self) -> UnordItems<T, impl Iterator<Item = T>> {
132         UnordItems(self.0.copied())
133     }
134 }
135 
136 impl<T: Ord, I: Iterator<Item = T>> UnordItems<T, I> {
into_sorted<HCX>(self, hcx: &HCX) -> Vec<T> where T: ToStableHashKey<HCX>,137     pub fn into_sorted<HCX>(self, hcx: &HCX) -> Vec<T>
138     where
139         T: ToStableHashKey<HCX>,
140     {
141         let mut items: Vec<T> = self.0.collect();
142         items.sort_by_cached_key(|x| x.to_stable_hash_key(hcx));
143         items
144     }
145 
146     #[inline]
into_sorted_stable_ord(self) -> Vec<T> where T: Ord + StableOrd,147     pub fn into_sorted_stable_ord(self) -> Vec<T>
148     where
149         T: Ord + StableOrd,
150     {
151         let mut items: Vec<T> = self.0.collect();
152         if !T::CAN_USE_UNSTABLE_SORT {
153             items.sort();
154         } else {
155             items.sort_unstable()
156         }
157         items
158     }
159 
into_sorted_small_vec<HCX, const LEN: usize>(self, hcx: &HCX) -> SmallVec<[T; LEN]> where T: ToStableHashKey<HCX>,160     pub fn into_sorted_small_vec<HCX, const LEN: usize>(self, hcx: &HCX) -> SmallVec<[T; LEN]>
161     where
162         T: ToStableHashKey<HCX>,
163     {
164         let mut items: SmallVec<[T; LEN]> = self.0.collect();
165         items.sort_by_cached_key(|x| x.to_stable_hash_key(hcx));
166         items
167     }
168 }
169 
170 /// This is a set collection type that tries very hard to not expose
171 /// any internal iteration. This is a useful property when trying to
172 /// uphold the determinism invariants imposed by the query system.
173 ///
174 /// This collection type is a good choice for set-like collections the
175 /// keys of which don't have a semantic ordering.
176 ///
177 /// See [MCP 533](https://github.com/rust-lang/compiler-team/issues/533)
178 /// for more information.
179 #[derive(Debug, Eq, PartialEq, Clone, Encodable, Decodable)]
180 pub struct UnordSet<V: Eq + Hash> {
181     inner: FxHashSet<V>,
182 }
183 
184 impl<V: Eq + Hash> Default for UnordSet<V> {
185     #[inline]
default() -> Self186     fn default() -> Self {
187         Self { inner: FxHashSet::default() }
188     }
189 }
190 
191 impl<V: Eq + Hash> UnordSet<V> {
192     #[inline]
new() -> Self193     pub fn new() -> Self {
194         Self { inner: Default::default() }
195     }
196 
197     #[inline]
len(&self) -> usize198     pub fn len(&self) -> usize {
199         self.inner.len()
200     }
201 
202     #[inline]
is_empty(&self) -> bool203     pub fn is_empty(&self) -> bool {
204         self.inner.is_empty()
205     }
206 
207     #[inline]
insert(&mut self, v: V) -> bool208     pub fn insert(&mut self, v: V) -> bool {
209         self.inner.insert(v)
210     }
211 
212     #[inline]
contains<Q: ?Sized>(&self, v: &Q) -> bool where V: Borrow<Q>, Q: Hash + Eq,213     pub fn contains<Q: ?Sized>(&self, v: &Q) -> bool
214     where
215         V: Borrow<Q>,
216         Q: Hash + Eq,
217     {
218         self.inner.contains(v)
219     }
220 
221     #[inline]
remove<Q: ?Sized>(&mut self, k: &Q) -> bool where V: Borrow<Q>, Q: Hash + Eq,222     pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> bool
223     where
224         V: Borrow<Q>,
225         Q: Hash + Eq,
226     {
227         self.inner.remove(k)
228     }
229 
230     #[inline]
items(&self) -> UnordItems<&V, impl Iterator<Item = &V>>231     pub fn items(&self) -> UnordItems<&V, impl Iterator<Item = &V>> {
232         UnordItems(self.inner.iter())
233     }
234 
235     #[inline]
into_items(self) -> UnordItems<V, impl Iterator<Item = V>>236     pub fn into_items(self) -> UnordItems<V, impl Iterator<Item = V>> {
237         UnordItems(self.inner.into_iter())
238     }
239 
240     /// Returns the items of this set in stable sort order (as defined by `ToStableHashKey`).
241     ///
242     /// The `cache_sort_key` parameter controls if [slice::sort_by_cached_key] or
243     /// [slice::sort_unstable_by_key] will be used for sorting the vec. Use
244     /// `cache_sort_key` when the [ToStableHashKey::to_stable_hash_key] implementation
245     /// for `V` is expensive (e.g. a `DefId -> DefPathHash` lookup).
246     #[inline]
to_sorted<HCX>(&self, hcx: &HCX, cache_sort_key: bool) -> Vec<&V> where V: ToStableHashKey<HCX>,247     pub fn to_sorted<HCX>(&self, hcx: &HCX, cache_sort_key: bool) -> Vec<&V>
248     where
249         V: ToStableHashKey<HCX>,
250     {
251         to_sorted_vec(hcx, self.inner.iter(), cache_sort_key, |&x| x)
252     }
253 
254     /// Returns the items of this set in stable sort order (as defined by
255     /// `StableOrd`). This method is much more efficient than
256     /// `into_sorted` because it does not need to transform keys to their
257     /// `ToStableHashKey` equivalent.
258     #[inline]
to_sorted_stable_ord(&self) -> Vec<V> where V: Ord + StableOrd + Copy,259     pub fn to_sorted_stable_ord(&self) -> Vec<V>
260     where
261         V: Ord + StableOrd + Copy,
262     {
263         let mut items: Vec<V> = self.inner.iter().copied().collect();
264         items.sort_unstable();
265         items
266     }
267 
268     /// Returns the items of this set in stable sort order (as defined by `ToStableHashKey`).
269     ///
270     /// The `cache_sort_key` parameter controls if [slice::sort_by_cached_key] or
271     /// [slice::sort_unstable_by_key] will be used for sorting the vec. Use
272     /// `cache_sort_key` when the [ToStableHashKey::to_stable_hash_key] implementation
273     /// for `V` is expensive (e.g. a `DefId -> DefPathHash` lookup).
274     #[inline]
into_sorted<HCX>(self, hcx: &HCX, cache_sort_key: bool) -> Vec<V> where V: ToStableHashKey<HCX>,275     pub fn into_sorted<HCX>(self, hcx: &HCX, cache_sort_key: bool) -> Vec<V>
276     where
277         V: ToStableHashKey<HCX>,
278     {
279         to_sorted_vec(hcx, self.inner.into_iter(), cache_sort_key, |x| x)
280     }
281 
282     // We can safely extend this UnordSet from a set of unordered values because that
283     // won't expose the internal ordering anywhere.
284     #[inline]
extend_unord<I: Iterator<Item = V>>(&mut self, items: UnordItems<V, I>)285     pub fn extend_unord<I: Iterator<Item = V>>(&mut self, items: UnordItems<V, I>) {
286         self.inner.extend(items.0)
287     }
288 
289     #[inline]
clear(&mut self)290     pub fn clear(&mut self) {
291         self.inner.clear();
292     }
293 }
294 
295 impl<V: Hash + Eq> Extend<V> for UnordSet<V> {
296     #[inline]
extend<T: IntoIterator<Item = V>>(&mut self, iter: T)297     fn extend<T: IntoIterator<Item = V>>(&mut self, iter: T) {
298         self.inner.extend(iter)
299     }
300 }
301 
302 impl<V: Hash + Eq> FromIterator<V> for UnordSet<V> {
303     #[inline]
from_iter<T: IntoIterator<Item = V>>(iter: T) -> Self304     fn from_iter<T: IntoIterator<Item = V>>(iter: T) -> Self {
305         UnordSet { inner: FxHashSet::from_iter(iter) }
306     }
307 }
308 
309 impl<V: Hash + Eq> From<FxHashSet<V>> for UnordSet<V> {
from(value: FxHashSet<V>) -> Self310     fn from(value: FxHashSet<V>) -> Self {
311         UnordSet { inner: value }
312     }
313 }
314 
315 impl<HCX, V: Hash + Eq + HashStable<HCX>> HashStable<HCX> for UnordSet<V> {
316     #[inline]
hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher)317     fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
318         hash_iter_order_independent(self.inner.iter(), hcx, hasher);
319     }
320 }
321 
322 /// This is a map collection type that tries very hard to not expose
323 /// any internal iteration. This is a useful property when trying to
324 /// uphold the determinism invariants imposed by the query system.
325 ///
326 /// This collection type is a good choice for map-like collections the
327 /// keys of which don't have a semantic ordering.
328 ///
329 /// See [MCP 533](https://github.com/rust-lang/compiler-team/issues/533)
330 /// for more information.
331 #[derive(Debug, Eq, PartialEq, Clone, Encodable, Decodable)]
332 pub struct UnordMap<K: Eq + Hash, V> {
333     inner: FxHashMap<K, V>,
334 }
335 
336 impl<K: Eq + Hash, V> Default for UnordMap<K, V> {
337     #[inline]
default() -> Self338     fn default() -> Self {
339         Self { inner: FxHashMap::default() }
340     }
341 }
342 
343 impl<K: Hash + Eq, V> Extend<(K, V)> for UnordMap<K, V> {
344     #[inline]
extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T)345     fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
346         self.inner.extend(iter)
347     }
348 }
349 
350 impl<K: Hash + Eq, V> FromIterator<(K, V)> for UnordMap<K, V> {
351     #[inline]
from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self352     fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
353         UnordMap { inner: FxHashMap::from_iter(iter) }
354     }
355 }
356 
357 impl<K: Hash + Eq, V, I: Iterator<Item = (K, V)>> From<UnordItems<(K, V), I>> for UnordMap<K, V> {
358     #[inline]
from(items: UnordItems<(K, V), I>) -> Self359     fn from(items: UnordItems<(K, V), I>) -> Self {
360         UnordMap { inner: FxHashMap::from_iter(items.0) }
361     }
362 }
363 
364 impl<K: Eq + Hash, V> UnordMap<K, V> {
365     #[inline]
len(&self) -> usize366     pub fn len(&self) -> usize {
367         self.inner.len()
368     }
369 
370     #[inline]
insert(&mut self, k: K, v: V) -> Option<V>371     pub fn insert(&mut self, k: K, v: V) -> Option<V> {
372         self.inner.insert(k, v)
373     }
374 
375     #[inline]
contains_key<Q: ?Sized>(&self, k: &Q) -> bool where K: Borrow<Q>, Q: Hash + Eq,376     pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
377     where
378         K: Borrow<Q>,
379         Q: Hash + Eq,
380     {
381         self.inner.contains_key(k)
382     }
383 
384     #[inline]
is_empty(&self) -> bool385     pub fn is_empty(&self) -> bool {
386         self.inner.is_empty()
387     }
388 
389     #[inline]
entry(&mut self, key: K) -> Entry<'_, K, V>390     pub fn entry(&mut self, key: K) -> Entry<'_, K, V> {
391         self.inner.entry(key)
392     }
393 
394     #[inline]
get<Q: ?Sized>(&self, k: &Q) -> Option<&V> where K: Borrow<Q>, Q: Hash + Eq,395     pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
396     where
397         K: Borrow<Q>,
398         Q: Hash + Eq,
399     {
400         self.inner.get(k)
401     }
402 
403     #[inline]
get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V> where K: Borrow<Q>, Q: Hash + Eq,404     pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
405     where
406         K: Borrow<Q>,
407         Q: Hash + Eq,
408     {
409         self.inner.get_mut(k)
410     }
411 
412     #[inline]
remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V> where K: Borrow<Q>, Q: Hash + Eq,413     pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
414     where
415         K: Borrow<Q>,
416         Q: Hash + Eq,
417     {
418         self.inner.remove(k)
419     }
420 
421     #[inline]
items(&self) -> UnordItems<(&K, &V), impl Iterator<Item = (&K, &V)>>422     pub fn items(&self) -> UnordItems<(&K, &V), impl Iterator<Item = (&K, &V)>> {
423         UnordItems(self.inner.iter())
424     }
425 
426     #[inline]
into_items(self) -> UnordItems<(K, V), impl Iterator<Item = (K, V)>>427     pub fn into_items(self) -> UnordItems<(K, V), impl Iterator<Item = (K, V)>> {
428         UnordItems(self.inner.into_iter())
429     }
430 
431     // We can safely extend this UnordMap from a set of unordered values because that
432     // won't expose the internal ordering anywhere.
433     #[inline]
extend<I: Iterator<Item = (K, V)>>(&mut self, items: UnordItems<(K, V), I>)434     pub fn extend<I: Iterator<Item = (K, V)>>(&mut self, items: UnordItems<(K, V), I>) {
435         self.inner.extend(items.0)
436     }
437 
438     /// Returns the entries of this map in stable sort order (as defined by `ToStableHashKey`).
439     ///
440     /// The `cache_sort_key` parameter controls if [slice::sort_by_cached_key] or
441     /// [slice::sort_unstable_by_key] will be used for sorting the vec. Use
442     /// `cache_sort_key` when the [ToStableHashKey::to_stable_hash_key] implementation
443     /// for `K` is expensive (e.g. a `DefId -> DefPathHash` lookup).
444     #[inline]
to_sorted<HCX>(&self, hcx: &HCX, cache_sort_key: bool) -> Vec<(&K, &V)> where K: ToStableHashKey<HCX>,445     pub fn to_sorted<HCX>(&self, hcx: &HCX, cache_sort_key: bool) -> Vec<(&K, &V)>
446     where
447         K: ToStableHashKey<HCX>,
448     {
449         to_sorted_vec(hcx, self.inner.iter(), cache_sort_key, |&(k, _)| k)
450     }
451 
452     /// Returns the entries of this map in stable sort order (as defined by `StableOrd`).
453     /// This method can be much more efficient than `into_sorted` because it does not need
454     /// to transform keys to their `ToStableHashKey` equivalent.
455     #[inline]
to_sorted_stable_ord(&self) -> Vec<(K, &V)> where K: Ord + StableOrd + Copy,456     pub fn to_sorted_stable_ord(&self) -> Vec<(K, &V)>
457     where
458         K: Ord + StableOrd + Copy,
459     {
460         let mut items: Vec<(K, &V)> = self.inner.iter().map(|(&k, v)| (k, v)).collect();
461         items.sort_unstable_by_key(|&(k, _)| k);
462         items
463     }
464 
465     /// Returns the entries of this map in stable sort order (as defined by `ToStableHashKey`).
466     ///
467     /// The `cache_sort_key` parameter controls if [slice::sort_by_cached_key] or
468     /// [slice::sort_unstable_by_key] will be used for sorting the vec. Use
469     /// `cache_sort_key` when the [ToStableHashKey::to_stable_hash_key] implementation
470     /// for `K` is expensive (e.g. a `DefId -> DefPathHash` lookup).
471     #[inline]
into_sorted<HCX>(self, hcx: &HCX, cache_sort_key: bool) -> Vec<(K, V)> where K: ToStableHashKey<HCX>,472     pub fn into_sorted<HCX>(self, hcx: &HCX, cache_sort_key: bool) -> Vec<(K, V)>
473     where
474         K: ToStableHashKey<HCX>,
475     {
476         to_sorted_vec(hcx, self.inner.into_iter(), cache_sort_key, |(k, _)| k)
477     }
478 
479     /// Returns the values of this map in stable sort order (as defined by K's
480     /// `ToStableHashKey` implementation).
481     ///
482     /// The `cache_sort_key` parameter controls if [slice::sort_by_cached_key] or
483     /// [slice::sort_unstable_by_key] will be used for sorting the vec. Use
484     /// `cache_sort_key` when the [ToStableHashKey::to_stable_hash_key] implementation
485     /// for `K` is expensive (e.g. a `DefId -> DefPathHash` lookup).
486     #[inline]
values_sorted<HCX>(&self, hcx: &HCX, cache_sort_key: bool) -> impl Iterator<Item = &V> where K: ToStableHashKey<HCX>,487     pub fn values_sorted<HCX>(&self, hcx: &HCX, cache_sort_key: bool) -> impl Iterator<Item = &V>
488     where
489         K: ToStableHashKey<HCX>,
490     {
491         to_sorted_vec(hcx, self.inner.iter(), cache_sort_key, |&(k, _)| k)
492             .into_iter()
493             .map(|(_, v)| v)
494     }
495 }
496 
497 impl<K, Q: ?Sized, V> Index<&Q> for UnordMap<K, V>
498 where
499     K: Eq + Hash + Borrow<Q>,
500     Q: Eq + Hash,
501 {
502     type Output = V;
503 
504     #[inline]
index(&self, key: &Q) -> &V505     fn index(&self, key: &Q) -> &V {
506         &self.inner[key]
507     }
508 }
509 
510 impl<HCX, K: Hash + Eq + HashStable<HCX>, V: HashStable<HCX>> HashStable<HCX> for UnordMap<K, V> {
511     #[inline]
hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher)512     fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
513         hash_iter_order_independent(self.inner.iter(), hcx, hasher);
514     }
515 }
516 
517 /// This is a collection type that tries very hard to not expose
518 /// any internal iteration. This is a useful property when trying to
519 /// uphold the determinism invariants imposed by the query system.
520 ///
521 /// This collection type is a good choice for collections the
522 /// keys of which don't have a semantic ordering and don't implement
523 /// `Hash` or `Eq`.
524 ///
525 /// See [MCP 533](https://github.com/rust-lang/compiler-team/issues/533)
526 /// for more information.
527 #[derive(Default, Debug, Eq, PartialEq, Clone, Encodable, Decodable)]
528 pub struct UnordBag<V> {
529     inner: Vec<V>,
530 }
531 
532 impl<V> UnordBag<V> {
533     #[inline]
new() -> Self534     pub fn new() -> Self {
535         Self { inner: Default::default() }
536     }
537 
538     #[inline]
len(&self) -> usize539     pub fn len(&self) -> usize {
540         self.inner.len()
541     }
542 
543     #[inline]
push(&mut self, v: V)544     pub fn push(&mut self, v: V) {
545         self.inner.push(v);
546     }
547 
548     #[inline]
items(&self) -> UnordItems<&V, impl Iterator<Item = &V>>549     pub fn items(&self) -> UnordItems<&V, impl Iterator<Item = &V>> {
550         UnordItems(self.inner.iter())
551     }
552 
553     #[inline]
into_items(self) -> UnordItems<V, impl Iterator<Item = V>>554     pub fn into_items(self) -> UnordItems<V, impl Iterator<Item = V>> {
555         UnordItems(self.inner.into_iter())
556     }
557 
558     // We can safely extend this UnordSet from a set of unordered values because that
559     // won't expose the internal ordering anywhere.
560     #[inline]
extend<I: Iterator<Item = V>>(&mut self, items: UnordItems<V, I>)561     pub fn extend<I: Iterator<Item = V>>(&mut self, items: UnordItems<V, I>) {
562         self.inner.extend(items.0)
563     }
564 }
565 
566 impl<T> Extend<T> for UnordBag<T> {
extend<I: IntoIterator<Item = T>>(&mut self, iter: I)567     fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
568         self.inner.extend(iter)
569     }
570 }
571 
572 impl<T, I: Iterator<Item = T>> From<UnordItems<T, I>> for UnordBag<T> {
from(value: UnordItems<T, I>) -> Self573     fn from(value: UnordItems<T, I>) -> Self {
574         UnordBag { inner: Vec::from_iter(value.0) }
575     }
576 }
577 
578 impl<HCX, V: Hash + Eq + HashStable<HCX>> HashStable<HCX> for UnordBag<V> {
579     #[inline]
hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher)580     fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
581         hash_iter_order_independent(self.inner.iter(), hcx, hasher);
582     }
583 }
584 
585 #[inline]
to_sorted_vec<HCX, T, K, I>( hcx: &HCX, iter: I, cache_sort_key: bool, extract_key: fn(&T) -> &K, ) -> Vec<T> where I: Iterator<Item = T>, K: ToStableHashKey<HCX>,586 fn to_sorted_vec<HCX, T, K, I>(
587     hcx: &HCX,
588     iter: I,
589     cache_sort_key: bool,
590     extract_key: fn(&T) -> &K,
591 ) -> Vec<T>
592 where
593     I: Iterator<Item = T>,
594     K: ToStableHashKey<HCX>,
595 {
596     let mut items: Vec<T> = iter.collect();
597     if cache_sort_key {
598         items.sort_by_cached_key(|x| extract_key(x).to_stable_hash_key(hcx));
599     } else {
600         items.sort_unstable_by_key(|x| extract_key(x).to_stable_hash_key(hcx));
601     }
602 
603     items
604 }
605 
hash_iter_order_independent< HCX, T: HashStable<HCX>, I: Iterator<Item = T> + ExactSizeIterator, >( mut it: I, hcx: &mut HCX, hasher: &mut StableHasher, )606 fn hash_iter_order_independent<
607     HCX,
608     T: HashStable<HCX>,
609     I: Iterator<Item = T> + ExactSizeIterator,
610 >(
611     mut it: I,
612     hcx: &mut HCX,
613     hasher: &mut StableHasher,
614 ) {
615     let len = it.len();
616     len.hash_stable(hcx, hasher);
617 
618     match len {
619         0 => {
620             // We're done
621         }
622         1 => {
623             // No need to instantiate a hasher
624             it.next().unwrap().hash_stable(hcx, hasher);
625         }
626         _ => {
627             let mut accumulator = Fingerprint::ZERO;
628             for item in it {
629                 let mut item_hasher = StableHasher::new();
630                 item.hash_stable(hcx, &mut item_hasher);
631                 let item_fingerprint: Fingerprint = item_hasher.finish();
632                 accumulator = accumulator.combine_commutative(item_fingerprint);
633             }
634             accumulator.hash_stable(hcx, hasher);
635         }
636     }
637 }
638 
639 // Do not implement IntoIterator for the collections in this module.
640 // They only exist to hide iteration order in the first place.
641 impl<T> !IntoIterator for UnordBag<T> {}
642 impl<V> !IntoIterator for UnordSet<V> {}
643 impl<K, V> !IntoIterator for UnordMap<K, V> {}
644 impl<T, I> !IntoIterator for UnordItems<T, I> {}
645