Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit b8c2074

Browse files
committed
Auto merge of #119192 - michaelwoerister:mcp533-push, r=cjgillot
Replace a number of FxHashMaps/Sets with stable-iteration-order alternatives This PR replaces almost all of the remaining `FxHashMap`s in query results with either `FxIndexMap` or `UnordMap`. The only case that is missing is the `EffectiveVisibilities` struct which turned out to not be straightforward to transform. Once that is done too, we can remove the `HashStable` implementation from `HashMap`. The first commit adds the `StableCompare` trait which is a companion trait to `StableOrd`. Some types like `Symbol` can be compared in a cross-session stable way, but their `Ord` implementation is not stable. In such cases, a `StableCompare` implementation can be provided to offer a lightweight way for stable sorting. The more heavyweight option is to sort via `ToStableHashKey`, but then sorting needs to have access to a stable hashing context and `ToStableHashKey` can also be expensive as in the case of `Symbol` where it has to allocate a `String`. The rest of the commits are rather mechanical and don't overlap, so they are best reviewed individually. Part of [MCP 533](rust-lang/compiler-team#533).
2 parents 11035f9 + 077540c commit b8c2074

File tree

30 files changed

+256
-147
lines changed

30 files changed

+256
-147
lines changed

‎compiler/rustc_codegen_ssa/src/back/symbol_export.rs‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::base::allocator_kind_for_codegen;
33
use std::collections::hash_map::Entry::*;
44

55
use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE};
6-
use rustc_data_structures::fx::FxHashMap;
6+
use rustc_data_structures::unord::UnordMap;
77
use rustc_hir::def::DefKind;
88
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
99
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
@@ -393,10 +393,10 @@ fn exported_symbols_provider_local(
393393
fn upstream_monomorphizations_provider(
394394
tcx: TyCtxt<'_>,
395395
(): (),
396-
) -> DefIdMap<FxHashMap<GenericArgsRef<'_>, CrateNum>> {
396+
) -> DefIdMap<UnordMap<GenericArgsRef<'_>, CrateNum>> {
397397
let cnums = tcx.crates(());
398398

399-
let mut instances: DefIdMap<FxHashMap<_, _>> = Default::default();
399+
let mut instances: DefIdMap<UnordMap<_, _>> = Default::default();
400400

401401
let drop_in_place_fn_def_id = tcx.lang_items().drop_in_place_fn();
402402

@@ -445,7 +445,7 @@ fn upstream_monomorphizations_provider(
445445
fn upstream_monomorphizations_for_provider(
446446
tcx: TyCtxt<'_>,
447447
def_id: DefId,
448-
) -> Option<&FxHashMap<GenericArgsRef<'_>, CrateNum>> {
448+
) -> Option<&UnordMap<GenericArgsRef<'_>, CrateNum>> {
449449
debug_assert!(!def_id.is_local());
450450
tcx.upstream_monomorphizations(()).get(&def_id)
451451
}
@@ -656,7 +656,7 @@ fn maybe_emutls_symbol_name<'tcx>(
656656
}
657657
}
658658

659-
fn wasm_import_module_map(tcx: TyCtxt<'_>, cnum: CrateNum) -> FxHashMap<DefId,String> {
659+
fn wasm_import_module_map(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap<String> {
660660
// Build up a map from DefId to a `NativeLib` structure, where
661661
// `NativeLib` internally contains information about
662662
// `#[link(wasm_import_module = "...")]` for example.
@@ -665,9 +665,9 @@ fn wasm_import_module_map(tcx: TyCtxt<'_>, cnum: CrateNum) -> FxHashMap<DefId, S
665665
let def_id_to_native_lib = native_libs
666666
.iter()
667667
.filter_map(|lib| lib.foreign_module.map(|id| (id, lib)))
668-
.collect::<FxHashMap<_,_>>();
668+
.collect::<DefIdMap<_>>();
669669

670-
let mut ret = FxHashMap::default();
670+
let mut ret = DefIdMap::default();
671671
for (def_id, lib) in tcx.foreign_modules(cnum).iter() {
672672
let module = def_id_to_native_lib.get(def_id).and_then(|s| s.wasm_import_module());
673673
let Some(module) = module else { continue };

‎compiler/rustc_codegen_ssa/src/target_features.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use crate::errors;
22
use rustc_ast::ast;
33
use rustc_attr::InstructionSetAttr;
4-
use rustc_data_structures::fx::FxHashMap;
54
use rustc_data_structures::fx::FxIndexSet;
5+
use rustc_data_structures::unord::UnordMap;
66
use rustc_errors::Applicability;
77
use rustc_hir::def::DefKind;
88
use rustc_hir::def_id::DefId;
@@ -18,7 +18,7 @@ use rustc_span::Span;
1818
pub fn from_target_feature(
1919
tcx: TyCtxt<'_>,
2020
attr: &ast::Attribute,
21-
supported_target_features: &FxHashMap<String, Option<Symbol>>,
21+
supported_target_features: &UnordMap<String, Option<Symbol>>,
2222
target_features: &mut Vec<Symbol>,
2323
) {
2424
let Some(list) = attr.meta_item_list() else { return };

‎compiler/rustc_data_structures/src/stable_hasher.rs‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,32 @@ unsafe impl<T: StableOrd> StableOrd for &T {
245245
const CAN_USE_UNSTABLE_SORT: bool = T::CAN_USE_UNSTABLE_SORT;
246246
}
247247

248+
/// This is a companion trait to `StableOrd`. Some types like `Symbol` can be
249+
/// compared in a cross-session stable way, but their `Ord` implementation is
250+
/// not stable. In such cases, a `StableOrd` implementation can be provided
251+
/// to offer a lightweight way for stable sorting. (The more heavyweight option
252+
/// is to sort via `ToStableHashKey`, but then sorting needs to have access to
253+
/// a stable hashing context and `ToStableHashKey` can also be expensive as in
254+
/// the case of `Symbol` where it has to allocate a `String`.)
255+
///
256+
/// See the documentation of [StableOrd] for how stable sort order is defined.
257+
/// The same definition applies here. Be careful when implementing this trait.
258+
pub trait StableCompare {
259+
const CAN_USE_UNSTABLE_SORT: bool;
260+
261+
fn stable_cmp(&self, other: &Self) -> std::cmp::Ordering;
262+
}
263+
264+
/// `StableOrd` denotes that the type's `Ord` implementation is stable, so
265+
/// we can implement `StableCompare` by just delegating to `Ord`.
266+
impl<T: StableOrd> StableCompare for T {
267+
const CAN_USE_UNSTABLE_SORT: bool = T::CAN_USE_UNSTABLE_SORT;
268+
269+
fn stable_cmp(&self, other: &Self) -> std::cmp::Ordering {
270+
self.cmp(other)
271+
}
272+
}
273+
248274
/// Implement HashStable by just calling `Hash::hash()`. Also implement `StableOrd` for the type since
249275
/// that has the same requirements.
250276
///

‎compiler/rustc_data_structures/src/unord.rs‎

Lines changed: 95 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@
33
//! as required by the query system.
44
55
use rustc_hash::{FxHashMap, FxHashSet};
6-
use smallvec::SmallVec;
76
use std::{
8-
borrow::Borrow,
7+
borrow::{Borrow,BorrowMut},
98
collections::hash_map::Entry,
109
hash::Hash,
1110
iter::{Product, Sum},
@@ -14,7 +13,7 @@ use std::{
1413

1514
use crate::{
1615
fingerprint::Fingerprint,
17-
stable_hasher::{HashStable, StableHasher,StableOrd, ToStableHashKey},
16+
stable_hasher::{HashStable, StableCompare,StableHasher, ToStableHashKey},
1817
};
1918

2019
/// `UnordItems` is the order-less version of `Iterator`. It only contains methods
@@ -134,36 +133,78 @@ impl<'a, T: Copy + 'a, I: Iterator<Item = &'a T>> UnordItems<&'a T, I> {
134133
}
135134
}
136135

137-
impl<T: Ord, I: Iterator<Item = T>> UnordItems<T, I> {
136+
impl<T, I: Iterator<Item = T>> UnordItems<T, I> {
137+
#[inline]
138138
pub fn into_sorted<HCX>(self, hcx: &HCX) -> Vec<T>
139139
where
140140
T: ToStableHashKey<HCX>,
141141
{
142-
let mut items: Vec<T> = self.0.collect();
143-
items.sort_by_cached_key(|x| x.to_stable_hash_key(hcx));
144-
items
142+
self.collect_sorted(hcx, true)
145143
}
146144

147145
#[inline]
148146
pub fn into_sorted_stable_ord(self) -> Vec<T>
149147
where
150-
T: Ord + StableOrd,
148+
T: StableCompare,
149+
{
150+
self.collect_stable_ord_by_key(|x| x)
151+
}
152+
153+
#[inline]
154+
pub fn into_sorted_stable_ord_by_key<K, C>(self, project_to_key: C) -> Vec<T>
155+
where
156+
K: StableCompare,
157+
C: for<'a> Fn(&'a T) -> &'a K,
151158
{
152-
let mut items: Vec<T> = self.0.collect();
153-
if !T::CAN_USE_UNSTABLE_SORT {
154-
items.sort();
155-
} else {
156-
items.sort_unstable()
159+
self.collect_stable_ord_by_key(project_to_key)
160+
}
161+
162+
#[inline]
163+
pub fn collect_sorted<HCX, C>(self, hcx: &HCX, cache_sort_key: bool) -> C
164+
where
165+
T: ToStableHashKey<HCX>,
166+
C: FromIterator<T> + BorrowMut<[T]>,
167+
{
168+
let mut items: C = self.0.collect();
169+
170+
let slice = items.borrow_mut();
171+
if slice.len() > 1 {
172+
if cache_sort_key {
173+
slice.sort_by_cached_key(|x| x.to_stable_hash_key(hcx));
174+
} else {
175+
slice.sort_by_key(|x| x.to_stable_hash_key(hcx));
176+
}
157177
}
178+
158179
items
159180
}
160181

161-
pub fn into_sorted_small_vec<HCX, const LEN: usize>(self, hcx: &HCX) -> SmallVec<[T; LEN]>
182+
#[inline]
183+
pub fn collect_stable_ord_by_key<K, C, P>(self, project_to_key: P) -> C
162184
where
163-
T: ToStableHashKey<HCX>,
185+
K: StableCompare,
186+
P: for<'a> Fn(&'a T) -> &'a K,
187+
C: FromIterator<T> + BorrowMut<[T]>,
164188
{
165-
let mut items: SmallVec<[T; LEN]> = self.0.collect();
166-
items.sort_by_cached_key(|x| x.to_stable_hash_key(hcx));
189+
let mut items: C = self.0.collect();
190+
191+
let slice = items.borrow_mut();
192+
if slice.len() > 1 {
193+
if !K::CAN_USE_UNSTABLE_SORT {
194+
slice.sort_by(|a, b| {
195+
let a_key = project_to_key(a);
196+
let b_key = project_to_key(b);
197+
a_key.stable_cmp(b_key)
198+
});
199+
} else {
200+
slice.sort_unstable_by(|a, b| {
201+
let a_key = project_to_key(a);
202+
let b_key = project_to_key(b);
203+
a_key.stable_cmp(b_key)
204+
});
205+
}
206+
}
207+
167208
items
168209
}
169210
}
@@ -268,16 +309,30 @@ impl<V: Eq + Hash> UnordSet<V> {
268309
}
269310

270311
/// Returns the items of this set in stable sort order (as defined by
271-
/// `StableOrd`). This method is much more efficient than
312+
/// `StableCompare`). This method is much more efficient than
272313
/// `into_sorted` because it does not need to transform keys to their
273314
/// `ToStableHashKey` equivalent.
274315
#[inline]
275-
pub fn to_sorted_stable_ord(&self) -> Vec<V>
316+
pub fn to_sorted_stable_ord(&self) -> Vec<&V>
276317
where
277-
V: Ord + StableOrd + Clone,
318+
V: StableCompare,
278319
{
279-
let mut items: Vec<V> = self.inner.iter().cloned().collect();
280-
items.sort_unstable();
320+
let mut items: Vec<&V> = self.inner.iter().collect();
321+
items.sort_unstable_by(|a, b| a.stable_cmp(*b));
322+
items
323+
}
324+
325+
/// Returns the items of this set in stable sort order (as defined by
326+
/// `StableCompare`). This method is much more efficient than
327+
/// `into_sorted` because it does not need to transform keys to their
328+
/// `ToStableHashKey` equivalent.
329+
#[inline]
330+
pub fn into_sorted_stable_ord(self) -> Vec<V>
331+
where
332+
V: StableCompare,
333+
{
334+
let mut items: Vec<V> = self.inner.into_iter().collect();
335+
items.sort_unstable_by(V::stable_cmp);
281336
items
282337
}
283338

@@ -483,16 +538,16 @@ impl<K: Eq + Hash, V> UnordMap<K, V> {
483538
to_sorted_vec(hcx, self.inner.iter(), cache_sort_key, |&(k, _)| k)
484539
}
485540

486-
/// Returns the entries of this map in stable sort order (as defined by `StableOrd`).
541+
/// Returns the entries of this map in stable sort order (as defined by `StableCompare`).
487542
/// This method can be much more efficient than `into_sorted` because it does not need
488543
/// to transform keys to their `ToStableHashKey` equivalent.
489544
#[inline]
490-
pub fn to_sorted_stable_ord(&self) -> Vec<(K, &V)>
545+
pub fn to_sorted_stable_ord(&self) -> Vec<(&K, &V)>
491546
where
492-
K: Ord + StableOrd + Copy,
547+
K: StableCompare,
493548
{
494-
let mut items: Vec<(K,&V)> = self.inner.iter().map(|(&k, v)| (k, v)).collect();
495-
items.sort_unstable_by_key(|&(k, _)| k);
549+
let mut items: Vec<_> = self.inner.iter().collect();
550+
items.sort_unstable_by(|(a, _),(b, _)| a.stable_cmp(*b));
496551
items
497552
}
498553

@@ -510,6 +565,19 @@ impl<K: Eq + Hash, V> UnordMap<K, V> {
510565
to_sorted_vec(hcx, self.inner.into_iter(), cache_sort_key, |(k, _)| k)
511566
}
512567

568+
/// Returns the entries of this map in stable sort order (as defined by `StableCompare`).
569+
/// This method can be much more efficient than `into_sorted` because it does not need
570+
/// to transform keys to their `ToStableHashKey` equivalent.
571+
#[inline]
572+
pub fn into_sorted_stable_ord(self) -> Vec<(K, V)>
573+
where
574+
K: StableCompare,
575+
{
576+
let mut items: Vec<(K, V)> = self.inner.into_iter().collect();
577+
items.sort_unstable_by(|a, b| a.0.stable_cmp(&b.0));
578+
items
579+
}
580+
513581
/// Returns the values of this map in stable sort order (as defined by K's
514582
/// `ToStableHashKey` implementation).
515583
///

‎compiler/rustc_hir_analysis/src/astconv/errors.rs‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::errors::{
66
use crate::fluent_generated as fluent;
77
use crate::traits::error_reporting::report_object_safety_error;
88
use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet};
9+
use rustc_data_structures::unord::UnordMap;
910
use rustc_errors::{pluralize, struct_span_err, Applicability, Diagnostic, ErrorGuaranteed};
1011
use rustc_hir as hir;
1112
use rustc_hir::def_id::{DefId, LocalDefId};
@@ -673,7 +674,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
673674
}))
674675
})
675676
.flatten()
676-
.collect::<FxHashMap<Symbol, &ty::AssocItem>>();
677+
.collect::<UnordMap<Symbol, &ty::AssocItem>>();
677678

678679
let mut names = names
679680
.into_iter()
@@ -709,7 +710,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
709710
let mut where_constraints = vec![];
710711
let mut already_has_generics_args_suggestion = false;
711712
for (span, assoc_items) in &associated_types {
712-
let mut names: FxHashMap<_, usize> = FxHashMap::default();
713+
let mut names: UnordMap<_, usize> = Default::default();
713714
for item in assoc_items {
714715
types_count += 1;
715716
*names.entry(item.name).or_insert(0) += 1;

‎compiler/rustc_hir_analysis/src/check/compare_impl_item.rs‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::potentially_plural_count;
22
use crate::errors::LifetimesOrBoundsMismatchOnTrait;
3-
use hir::def_id::{DefId, LocalDefId};
3+
use hir::def_id::{DefId, DefIdMap,LocalDefId};
44
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
55
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed};
66
use rustc_hir as hir;
@@ -478,7 +478,7 @@ fn compare_asyncness<'tcx>(
478478
pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
479479
tcx: TyCtxt<'tcx>,
480480
impl_m_def_id: LocalDefId,
481-
) -> Result<&'tcx FxHashMap<DefId,ty::EarlyBinder<Ty<'tcx>>>, ErrorGuaranteed> {
481+
) -> Result<&'tcx DefIdMap<ty::EarlyBinder<Ty<'tcx>>>, ErrorGuaranteed> {
482482
let impl_m = tcx.opt_associated_item(impl_m_def_id.to_def_id()).unwrap();
483483
let trait_m = tcx.opt_associated_item(impl_m.trait_item_def_id.unwrap()).unwrap();
484484
let impl_trait_ref =
@@ -706,7 +706,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
706706
);
707707
ocx.resolve_regions_and_report_errors(impl_m_def_id, &outlives_env)?;
708708

709-
let mut remapped_types = FxHashMap::default();
709+
let mut remapped_types = DefIdMap::default();
710710
for (def_id, (ty, args)) in collected_types {
711711
match infcx.fully_resolve((ty, args)) {
712712
Ok((ty, args)) => {

‎compiler/rustc_hir_analysis/src/collect.rs‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
1717
use rustc_data_structures::captures::Captures;
1818
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
19+
use rustc_data_structures::unord::UnordMap;
1920
use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey};
2021
use rustc_hir as hir;
2122
use rustc_hir::def::DefKind;
@@ -979,7 +980,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
979980
})
980981
// Check for duplicates
981982
.and_then(|list| {
982-
let mut set: FxHashMap<Symbol, Span> = FxHashMap::default();
983+
let mut set: UnordMap<Symbol, Span> = Default::default();
983984
let mut no_dups = true;
984985

985986
for ident in &*list {

‎compiler/rustc_hir_typeck/src/method/suggest.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -913,7 +913,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
913913
for ((span, add_where_or_comma), obligations) in type_params.into_iter() {
914914
restrict_type_params = true;
915915
// #74886: Sort here so that the output is always the same.
916-
let obligations = obligations.to_sorted_stable_ord();
916+
let obligations = obligations.into_sorted_stable_ord();
917917
err.span_suggestion_verbose(
918918
span,
919919
format!(

‎compiler/rustc_hir_typeck/src/upvar.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -912,7 +912,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
912912
drop_order: bool,
913913
) -> MigrationWarningReason {
914914
MigrationWarningReason {
915-
auto_traits: auto_trait_reasons.to_sorted_stable_ord(),
915+
auto_traits: auto_trait_reasons.into_sorted_stable_ord(),
916916
drop_order,
917917
}
918918
}

‎compiler/rustc_hir_typeck/src/writeback.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
473473
assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
474474

475475
let fcx_coercion_casts = fcx_typeck_results.coercion_casts().to_sorted_stable_ord();
476-
for local_id in fcx_coercion_casts {
476+
for &local_id in fcx_coercion_casts {
477477
self.typeck_results.set_coercion_cast(local_id);
478478
}
479479
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /