@@ -31,6 +31,7 @@ use crate::{
3131///
3232/// It's still possible to do the same thing with an `Fn` by using interior mutability,
3333/// but the chance of doing it accidentally is reduced.
34+ #[ derive( Clone ) ]
3435pub struct UnordItems < T , I : Iterator < Item = T > > ( I ) ;
3536
3637impl < T , I : Iterator < Item = T > > UnordItems < T , I > {
@@ -167,6 +168,14 @@ impl<T: Ord, I: Iterator<Item = T>> UnordItems<T, I> {
167168 }
168169}
169170
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+
170179/// This is a set collection type that tries very hard to not expose
171180/// any internal iteration. This is a useful property when trying to
172181/// uphold the determinism invariants imposed by the query system.
@@ -181,6 +190,8 @@ pub struct UnordSet<V: Eq + Hash> {
181190 inner : FxHashSet < V > ,
182191}
183192
193+ impl < V : Eq + Hash > UnordCollection for UnordSet < V > { }
194+
184195impl < V : Eq + Hash > Default for UnordSet < V > {
185196 #[ inline]
186197 fn default ( ) -> Self {
@@ -194,6 +205,11 @@ impl<V: Eq + Hash> UnordSet<V> {
194205 Self { inner : Default :: default ( ) }
195206 }
196207
208+ #[ inline]
209+ pub fn with_capacity ( capacity : usize ) -> Self {
210+ Self { inner : FxHashSet :: with_capacity_and_hasher ( capacity, Default :: default ( ) ) }
211+ }
212+
197213 #[ inline]
198214 pub fn len ( & self ) -> usize {
199215 self . inner . len ( )
@@ -258,9 +274,9 @@ impl<V: Eq + Hash> UnordSet<V> {
258274 #[ inline]
259275 pub fn to_sorted_stable_ord ( & self ) -> Vec < V >
260276 where
261- V : Ord + StableOrd + Copy ,
277+ V : Ord + StableOrd + Clone ,
262278 {
263- let mut items: Vec < V > = self . inner . iter ( ) . copied ( ) . collect ( ) ;
279+ let mut items: Vec < V > = self . inner . iter ( ) . cloned ( ) . collect ( ) ;
264280 items. sort_unstable ( ) ;
265281 items
266282 }
@@ -279,16 +295,28 @@ impl<V: Eq + Hash> UnordSet<V> {
279295 to_sorted_vec ( hcx, self . inner . into_iter ( ) , cache_sort_key, |x| x)
280296 }
281297
282- // We can safely extend this UnordSet from a set of unordered values because that
283- // won't expose the internal ordering anywhere.
284298 #[ inline]
285- pub fn extend_unord < I : Iterator < Item = V > > ( & mut self , items : UnordItems < V , I > ) {
286- self . inner . extend ( items . 0 )
299+ pub fn clear ( & mut self ) {
300+ self . inner . clear ( ) ;
287301 }
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+ }
288312
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 {
289317 #[ inline]
290- pub fn clear ( & mut self ) {
291- self . inner . clear ( ) ;
318+ fn extend_unord < I : Iterator < Item = T > > ( & mut self , items : UnordItems < T , I > ) {
319+ self . extend ( items . 0 )
292320 }
293321}
294322
@@ -312,6 +340,12 @@ impl<V: Hash + Eq> From<FxHashSet<V>> for UnordSet<V> {
312340 }
313341}
314342
343+ impl < V : Hash + Eq , I : Iterator < Item = V > > From < UnordItems < V , I > > for UnordSet < V > {
344+ fn from ( value : UnordItems < V , I > ) -> Self {
345+ UnordSet { inner : FxHashSet :: from_iter ( value. 0 ) }
346+ }
347+ }
348+
315349impl < HCX , V : Hash + Eq + HashStable < HCX > > HashStable < HCX > for UnordSet < V > {
316350 #[ inline]
317351 fn hash_stable ( & self , hcx : & mut HCX , hasher : & mut StableHasher ) {
@@ -333,6 +367,8 @@ pub struct UnordMap<K: Eq + Hash, V> {
333367 inner : FxHashMap < K , V > ,
334368}
335369
370+ impl < K : Eq + Hash , V > UnordCollection for UnordMap < K , V > { }
371+
336372impl < K : Eq + Hash , V > Default for UnordMap < K , V > {
337373 #[ inline]
338374 fn default ( ) -> Self {
@@ -362,6 +398,11 @@ impl<K: Hash + Eq, V, I: Iterator<Item = (K, V)>> From<UnordItems<(K, V), I>> fo
362398}
363399
364400impl < K : Eq + Hash , V > UnordMap < K , V > {
401+ #[ inline]
402+ pub fn with_capacity ( capacity : usize ) -> Self {
403+ Self { inner : FxHashMap :: with_capacity_and_hasher ( capacity, Default :: default ( ) ) }
404+ }
405+
365406 #[ inline]
366407 pub fn len ( & self ) -> usize {
367408 self . inner . len ( )
@@ -428,13 +469,6 @@ impl<K: Eq + Hash, V> UnordMap<K, V> {
428469 UnordItems ( self . inner . into_iter ( ) )
429470 }
430471
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]
434- pub fn extend < I : Iterator < Item = ( K , V ) > > ( & mut self , items : UnordItems < ( K , V ) , I > ) {
435- self . inner . extend ( items. 0 )
436- }
437-
438472 /// Returns the entries of this map in stable sort order (as defined by `ToStableHashKey`).
439473 ///
440474 /// The `cache_sort_key` parameter controls if [slice::sort_by_cached_key] or
@@ -554,15 +588,10 @@ impl<V> UnordBag<V> {
554588 pub fn into_items ( self ) -> UnordItems < V , impl Iterator < Item = V > > {
555589 UnordItems ( self . inner . into_iter ( ) )
556590 }
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]
561- pub fn extend < I : Iterator < Item = V > > ( & mut self , items : UnordItems < V , I > ) {
562- self . inner . extend ( items. 0 )
563- }
564591}
565592
593+ impl < T > UnordCollection for UnordBag < T > { }
594+
566595impl < T > Extend < T > for UnordBag < T > {
567596 fn extend < I : IntoIterator < Item = T > > ( & mut self , iter : I ) {
568597 self . inner . extend ( iter)
0 commit comments