@@ -168,6 +168,14 @@ impl<T: Ord, I: Iterator<Item = T>> UnordItems<T, I> {
168
168
}
169
169
}
170
170
171
+ /// A marker trait specifying that `Self` can consume `UnordItems<_>` without
172
+ /// exposing any internal ordering.
173
+ ///
174
+ /// Note: right now this is just a marker trait. It could be extended to contain
175
+ /// some useful, common methods though, like `len`, `clear`, or the various
176
+ /// kinds of `to_sorted`.
177
+ trait UnordCollection {}
178
+
171
179
/// This is a set collection type that tries very hard to not expose
172
180
/// any internal iteration. This is a useful property when trying to
173
181
/// uphold the determinism invariants imposed by the query system.
@@ -182,6 +190,8 @@ pub struct UnordSet<V: Eq + Hash> {
182
190
inner: FxHashSet<V>,
183
191
}
184
192
193
+ impl<V: Eq + Hash> UnordCollection for UnordSet<V> {}
194
+
185
195
impl<V: Eq + Hash> Default for UnordSet<V> {
186
196
#[inline]
187
197
fn default() -> Self {
@@ -285,16 +295,28 @@ impl<V: Eq + Hash> UnordSet<V> {
285
295
to_sorted_vec(hcx, self.inner.into_iter(), cache_sort_key, |x| x)
286
296
}
287
297
288
- // We can safely extend this UnordSet from a set of unordered values because that
289
- // won't expose the internal ordering anywhere.
290
298
#[inline]
291
- pub fn extend_unord<I: Iterator<Item = V>> (&mut self, items: UnordItems<V, I> ) {
292
- self.inner.extend(items.0)
299
+ pub fn clear (&mut self) {
300
+ self.inner.clear();
293
301
}
302
+ }
303
+
304
+ pub trait ExtendUnord<T> {
305
+ /// Extend this unord collection with the given `UnordItems`.
306
+ /// This method is called `extend_unord` instead of just `extend` so it
307
+ /// does not conflict with `Extend::extend`. Otherwise there would be many
308
+ /// places where the two methods would have to be explicitly disambiguated
309
+ /// via UFCS.
310
+ fn extend_unord<I: Iterator<Item = T>>(&mut self, items: UnordItems<T, I>);
311
+ }
294
312
313
+ // Note: it is important that `C` implements `UnordCollection` in addition to
314
+ // `Extend`, otherwise this impl would leak the internal iteration order of
315
+ // `items`, e.g. when calling `some_vec.extend_unord(some_unord_items)`.
316
+ impl<C: Extend<T> + UnordCollection, T> ExtendUnord<T> for C {
295
317
#[inline]
296
- pub fn clear (&mut self) {
297
- self.inner.clear();
318
+ fn extend_unord<I: Iterator<Item = T>> (&mut self, items: UnordItems<T, I> ) {
319
+ self.extend(items.0)
298
320
}
299
321
}
300
322
@@ -345,6 +367,8 @@ pub struct UnordMap<K: Eq + Hash, V> {
345
367
inner: FxHashMap<K, V>,
346
368
}
347
369
370
+ impl<K: Eq + Hash, V> UnordCollection for UnordMap<K, V> {}
371
+
348
372
impl<K: Eq + Hash, V> Default for UnordMap<K, V> {
349
373
#[inline]
350
374
fn default() -> Self {
@@ -445,13 +469,6 @@ impl<K: Eq + Hash, V> UnordMap<K, V> {
445
469
UnordItems(self.inner.into_iter())
446
470
}
447
471
448
- // We can safely extend this UnordMap from a set of unordered values because that
449
- // won't expose the internal ordering anywhere.
450
- #[inline]
451
- pub fn extend<I: Iterator<Item = (K, V)>>(&mut self, items: UnordItems<(K, V), I>) {
452
- self.inner.extend(items.0)
453
- }
454
-
455
472
/// Returns the entries of this map in stable sort order (as defined by `ToStableHashKey`).
456
473
///
457
474
/// The `cache_sort_key` parameter controls if [slice::sort_by_cached_key] or
@@ -571,15 +588,10 @@ impl<V> UnordBag<V> {
571
588
pub fn into_items(self) -> UnordItems<V, impl Iterator<Item = V>> {
572
589
UnordItems(self.inner.into_iter())
573
590
}
574
-
575
- // We can safely extend this UnordSet from a set of unordered values because that
576
- // won't expose the internal ordering anywhere.
577
- #[inline]
578
- pub fn extend<I: Iterator<Item = V>>(&mut self, items: UnordItems<V, I>) {
579
- self.inner.extend(items.0)
580
- }
581
591
}
582
592
593
+ impl<T> UnordCollection for UnordBag<T> {}
594
+
583
595
impl<T> Extend<T> for UnordBag<T> {
584
596
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
585
597
self.inner.extend(iter)
0 commit comments