From 457b787a524e87a11d715ec26a24e68c8cf272d9 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 10 Jul 2023 13:02:52 +0200 Subject: Introduce ExtentUnord trait for collections that can safely consume UnordItems. --- compiler/rustc_data_structures/src/unord.rs | 52 ++++++++++++++++++----------- 1 file changed, 32 insertions(+), 20 deletions(-) (limited to 'compiler/rustc_data_structures') diff --git a/compiler/rustc_data_structures/src/unord.rs b/compiler/rustc_data_structures/src/unord.rs index ec779854f36..47c56eba7ad 100644 --- a/compiler/rustc_data_structures/src/unord.rs +++ b/compiler/rustc_data_structures/src/unord.rs @@ -168,6 +168,14 @@ impl> UnordItems { } } +/// A marker trait specifying that `Self` can consume `UnordItems<_>` without +/// exposing any internal ordering. +/// +/// Note: right now this is just a marker trait. It could be extended to contain +/// some useful, common methods though, like `len`, `clear`, or the various +/// kinds of `to_sorted`. +trait UnordCollection {} + /// This is a set collection type that tries very hard to not expose /// any internal iteration. This is a useful property when trying to /// uphold the determinism invariants imposed by the query system. @@ -182,6 +190,8 @@ pub struct UnordSet { inner: FxHashSet, } +impl UnordCollection for UnordSet {} + impl Default for UnordSet { #[inline] fn default() -> Self { @@ -285,16 +295,28 @@ impl UnordSet { 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_unord>(&mut self, items: UnordItems) { - self.inner.extend(items.0) + pub fn clear(&mut self) { + self.inner.clear(); } +} + +pub trait ExtendUnord { + /// Extend this unord collection with the given `UnordItems`. + /// This method is called `extend_unord` instead of just `extend` so it + /// does not conflict with `Extend::extend`. Otherwise there would be many + /// places where the two methods would have to be explicitly disambiguated + /// via UFCS. + fn extend_unord>(&mut self, items: UnordItems); +} +// Note: it is important that `C` implements `UnordCollection` in addition to +// `Extend`, otherwise this impl would leak the internal iteration order of +// `items`, e.g. when calling `some_vec.extend_unord(some_unord_items)`. +impl + UnordCollection, T> ExtendUnord for C { #[inline] - pub fn clear(&mut self) { - self.inner.clear(); + fn extend_unord>(&mut self, items: UnordItems) { + self.extend(items.0) } } @@ -345,6 +367,8 @@ pub struct UnordMap { inner: FxHashMap, } +impl UnordCollection for UnordMap {} + impl Default for UnordMap { #[inline] fn default() -> Self { @@ -445,13 +469,6 @@ impl UnordMap { UnordItems(self.inner.into_iter()) } - // We can safely extend this UnordMap from a set of unordered values because that - // won't expose the internal ordering anywhere. - #[inline] - 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 @@ -571,15 +588,10 @@ impl UnordBag { pub fn into_items(self) -> UnordItems> { UnordItems(self.inner.into_iter()) } - - // 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) - } } +impl UnordCollection for UnordBag {} + impl Extend for UnordBag { fn extend>(&mut self, iter: I) { self.inner.extend(iter) -- cgit 1.4.1-3-g733a5