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