Skip to content

Commit 457b787

Browse files
Introduce ExtentUnord trait for collections that can safely consume UnordItems.
1 parent cfb3109 commit 457b787

File tree

6 files changed

+39
-26
lines changed

6 files changed

+39
-26
lines changed

compiler/rustc_data_structures/src/unord.rs

+32-20
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,14 @@ impl<T: Ord, I: Iterator<Item = T>> UnordItems<T, I> {
168168
}
169169
}
170170

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+
171179
/// This is a set collection type that tries very hard to not expose
172180
/// any internal iteration. This is a useful property when trying to
173181
/// uphold the determinism invariants imposed by the query system.
@@ -182,6 +190,8 @@ pub struct UnordSet<V: Eq + Hash> {
182190
inner: FxHashSet<V>,
183191
}
184192

193+
impl<V: Eq + Hash> UnordCollection for UnordSet<V> {}
194+
185195
impl<V: Eq + Hash> Default for UnordSet<V> {
186196
#[inline]
187197
fn default() -> Self {
@@ -285,16 +295,28 @@ impl<V: Eq + Hash> UnordSet<V> {
285295
to_sorted_vec(hcx, self.inner.into_iter(), cache_sort_key, |x| x)
286296
}
287297

288-
// We can safely extend this UnordSet from a set of unordered values because that
289-
// won't expose the internal ordering anywhere.
290298
#[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();
293301
}
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+
}
294312

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 {
295317
#[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)
298320
}
299321
}
300322

@@ -345,6 +367,8 @@ pub struct UnordMap<K: Eq + Hash, V> {
345367
inner: FxHashMap<K, V>,
346368
}
347369

370+
impl<K: Eq + Hash, V> UnordCollection for UnordMap<K, V> {}
371+
348372
impl<K: Eq + Hash, V> Default for UnordMap<K, V> {
349373
#[inline]
350374
fn default() -> Self {
@@ -445,13 +469,6 @@ impl<K: Eq + Hash, V> UnordMap<K, V> {
445469
UnordItems(self.inner.into_iter())
446470
}
447471

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-
455472
/// Returns the entries of this map in stable sort order (as defined by `ToStableHashKey`).
456473
///
457474
/// The `cache_sort_key` parameter controls if [slice::sort_by_cached_key] or
@@ -571,15 +588,10 @@ impl<V> UnordBag<V> {
571588
pub fn into_items(self) -> UnordItems<V, impl Iterator<Item = V>> {
572589
UnordItems(self.inner.into_iter())
573590
}
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-
}
581591
}
582592

593+
impl<T> UnordCollection for UnordBag<T> {}
594+
583595
impl<T> Extend<T> for UnordBag<T> {
584596
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
585597
self.inner.extend(iter)

compiler/rustc_hir_analysis/src/check_unused.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc_data_structures::unord::UnordSet;
1+
use rustc_data_structures::unord::{ExtendUnord, UnordSet};
22
use rustc_hir::def::DefKind;
33
use rustc_hir::def_id::LocalDefId;
44
use rustc_middle::ty::TyCtxt;

compiler/rustc_hir_typeck/src/upvar.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
use super::FnCtxt;
3434

3535
use crate::expr_use_visitor as euv;
36-
use rustc_data_structures::unord::UnordSet;
36+
use rustc_data_structures::unord::{ExtendUnord, UnordSet};
3737
use rustc_errors::{Applicability, MultiSpan};
3838
use rustc_hir as hir;
3939
use rustc_hir::def_id::LocalDefId;

compiler/rustc_hir_typeck/src/writeback.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use crate::FnCtxt;
66
use hir::def_id::LocalDefId;
7+
use rustc_data_structures::unord::ExtendUnord;
78
use rustc_errors::{ErrorGuaranteed, StashKey};
89
use rustc_hir as hir;
910
use rustc_hir::intravisit::{self, Visitor};
@@ -526,7 +527,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
526527
let fcx_typeck_results = self.fcx.typeck_results.borrow();
527528
assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
528529

529-
self.typeck_results.user_provided_sigs.extend(
530+
self.typeck_results.user_provided_sigs.extend_unord(
530531
fcx_typeck_results.user_provided_sigs.items().map(|(&def_id, c_sig)| {
531532
if cfg!(debug_assertions) && c_sig.has_infer() {
532533
span_bug!(

compiler/rustc_middle/src/ty/typeck_results.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::{
99
};
1010
use rustc_data_structures::{
1111
fx::FxIndexMap,
12-
unord::{UnordItems, UnordSet},
12+
unord::{ExtendUnord, UnordItems, UnordSet},
1313
};
1414
use rustc_errors::ErrorGuaranteed;
1515
use rustc_hir as hir;
@@ -635,7 +635,7 @@ impl<'a, V> LocalTableInContextMut<'a, V> {
635635
&mut self,
636636
items: UnordItems<(hir::HirId, V), impl Iterator<Item = (hir::HirId, V)>>,
637637
) {
638-
self.data.extend(items.map(|(id, value)| {
638+
self.data.extend_unord(items.map(|(id, value)| {
639639
validate_hir_id_for_typeck_results(self.hir_owner, id);
640640
(id.local_id, value)
641641
}))

compiler/rustc_mir_transform/src/check_unsafety.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc_data_structures::unord::{UnordItems, UnordSet};
1+
use rustc_data_structures::unord::{ExtendUnord, UnordItems, UnordSet};
22
use rustc_hir as hir;
33
use rustc_hir::def::DefKind;
44
use rustc_hir::def_id::{DefId, LocalDefId};

0 commit comments

Comments
 (0)