From 739e5ef49e28ea4b2ab20bd28251a2299bd6889c Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 21 Dec 2023 10:27:34 +0100 Subject: [PATCH 01/14] Split StableCompare trait out of StableOrd trait. StableCompare 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 `StableOrd` 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`.) --- .../src/stable_hasher.rs | 26 ++++++ compiler/rustc_data_structures/src/unord.rs | 80 +++++++++++++++---- .../rustc_hir_typeck/src/method/suggest.rs | 2 +- compiler/rustc_hir_typeck/src/upvar.rs | 2 +- compiler/rustc_hir_typeck/src/writeback.rs | 2 +- .../rustc_incremental/src/persist/save.rs | 2 +- compiler/rustc_lint_defs/src/lib.rs | 12 ++- .../rustc_middle/src/ty/typeck_results.rs | 2 +- compiler/rustc_span/src/symbol.rs | 12 ++- 9 files changed, 118 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs index 6d75b0fb8a0..afe26f80de8 100644 --- a/compiler/rustc_data_structures/src/stable_hasher.rs +++ b/compiler/rustc_data_structures/src/stable_hasher.rs @@ -245,6 +245,32 @@ unsafe impl StableOrd for &T { const CAN_USE_UNSTABLE_SORT: bool = T::CAN_USE_UNSTABLE_SORT; } +/// This 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 `StableOrd` 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`.) +/// +/// See the documentation of [StableOrd] for how stable sort order is defined. +/// The same definition applies here. Be careful when implementing this trait. +pub trait StableCompare { + const CAN_USE_UNSTABLE_SORT: bool; + + fn stable_cmp(&self, other: &Self) -> std::cmp::Ordering; +} + +/// `StableOrd` denotes that the type's `Ord` implementation is stable, so +/// we can implement `StableCompare` by just delegating to `Ord`. +impl StableCompare for T { + const CAN_USE_UNSTABLE_SORT: bool = T::CAN_USE_UNSTABLE_SORT; + + fn stable_cmp(&self, other: &Self) -> std::cmp::Ordering { + self.cmp(other) + } +} + /// Implement HashStable by just calling `Hash::hash()`. Also implement `StableOrd` for the type since /// that has the same requirements. /// diff --git a/compiler/rustc_data_structures/src/unord.rs b/compiler/rustc_data_structures/src/unord.rs index 47c56eba7ad..2475713012d 100644 --- a/compiler/rustc_data_structures/src/unord.rs +++ b/compiler/rustc_data_structures/src/unord.rs @@ -14,7 +14,7 @@ use std::{ use crate::{ fingerprint::Fingerprint, - stable_hasher::{HashStable, StableHasher, StableOrd, ToStableHashKey}, + stable_hasher::{HashStable, StableCompare, StableHasher, ToStableHashKey}, }; /// `UnordItems` is the order-less version of `Iterator`. It only contains methods @@ -134,7 +134,7 @@ impl<'a, T: Copy + 'a, I: Iterator> UnordItems<&'a T, I> { } } -impl> UnordItems { +impl> UnordItems { pub fn into_sorted(self, hcx: &HCX) -> Vec where T: ToStableHashKey, @@ -147,13 +147,36 @@ impl> UnordItems { #[inline] pub fn into_sorted_stable_ord(self) -> Vec where - T: Ord + StableOrd, + T: StableCompare, { let mut items: Vec = self.0.collect(); if !T::CAN_USE_UNSTABLE_SORT { - items.sort(); + items.sort_by(T::stable_cmp); } else { - items.sort_unstable() + items.sort_unstable_by(T::stable_cmp) + } + items + } + + #[inline] + pub fn into_sorted_stable_ord_by_key(self, project_to_key: C) -> Vec + where + K: StableCompare, + C: for<'a> Fn(&'a T) -> &'a K, + { + let mut items: Vec = self.0.collect(); + if !K::CAN_USE_UNSTABLE_SORT { + items.sort_by(|a, b| { + let a_key = project_to_key(a); + let b_key = project_to_key(b); + a_key.stable_cmp(b_key) + }); + } else { + items.sort_unstable_by(|a, b| { + let a_key = project_to_key(a); + let b_key = project_to_key(b); + a_key.stable_cmp(b_key) + }); } items } @@ -268,16 +291,30 @@ impl UnordSet { } /// Returns the items of this set in stable sort order (as defined by - /// `StableOrd`). This method is much more efficient than + /// `StableCompare`). This method is much more efficient than /// `into_sorted` because it does not need to transform keys to their /// `ToStableHashKey` equivalent. #[inline] - pub fn to_sorted_stable_ord(&self) -> Vec + pub fn to_sorted_stable_ord(&self) -> Vec<&V> where - V: Ord + StableOrd + Clone, + V: StableCompare, { - let mut items: Vec = self.inner.iter().cloned().collect(); - items.sort_unstable(); + let mut items: Vec<&V> = self.inner.iter().collect(); + items.sort_unstable_by(|a, b| a.stable_cmp(*b)); + items + } + + /// Returns the items of this set in stable sort order (as defined by + /// `StableCompare`). This method is much more efficient than + /// `into_sorted` because it does not need to transform keys to their + /// `ToStableHashKey` equivalent. + #[inline] + pub fn into_sorted_stable_ord(self) -> Vec + where + V: StableCompare, + { + let mut items: Vec = self.inner.into_iter().collect(); + items.sort_unstable_by(V::stable_cmp); items } @@ -483,16 +520,16 @@ impl UnordMap { to_sorted_vec(hcx, self.inner.iter(), cache_sort_key, |&(k, _)| k) } - /// Returns the entries of this map in stable sort order (as defined by `StableOrd`). + /// Returns the entries of this map in stable sort order (as defined by `StableCompare`). /// This method can be much more efficient than `into_sorted` because it does not need /// to transform keys to their `ToStableHashKey` equivalent. #[inline] - pub fn to_sorted_stable_ord(&self) -> Vec<(K, &V)> + pub fn to_sorted_stable_ord(&self) -> Vec<(&K, &V)> where - K: Ord + StableOrd + Copy, + K: StableCompare, { - let mut items: Vec<(K, &V)> = self.inner.iter().map(|(&k, v)| (k, v)).collect(); - items.sort_unstable_by_key(|&(k, _)| k); + let mut items: Vec<_> = self.inner.iter().collect(); + items.sort_unstable_by(|(a, _), (b, _)| a.stable_cmp(*b)); items } @@ -510,6 +547,19 @@ impl UnordMap { to_sorted_vec(hcx, self.inner.into_iter(), cache_sort_key, |(k, _)| k) } + /// Returns the entries of this map in stable sort order (as defined by `StableCompare`). + /// This method can be much more efficient than `into_sorted` because it does not need + /// to transform keys to their `ToStableHashKey` equivalent. + #[inline] + pub fn into_sorted_stable_ord(self) -> Vec<(K, V)> + where + K: StableCompare, + { + let mut items: Vec<(K, V)> = self.inner.into_iter().collect(); + items.sort_unstable_by(|a, b| a.0.stable_cmp(&b.0)); + items + } + /// Returns the values of this map in stable sort order (as defined by K's /// `ToStableHashKey` implementation). /// diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 47fdd64796e..22a7ede601e 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -913,7 +913,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for ((span, add_where_or_comma), obligations) in type_params.into_iter() { restrict_type_params = true; // #74886: Sort here so that the output is always the same. - let obligations = obligations.to_sorted_stable_ord(); + let obligations = obligations.into_sorted_stable_ord(); err.span_suggestion_verbose( span, format!( diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 47b9d5f6503..f6b05e1b35a 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -912,7 +912,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { drop_order: bool, ) -> MigrationWarningReason { MigrationWarningReason { - auto_traits: auto_trait_reasons.to_sorted_stable_ord(), + auto_traits: auto_trait_reasons.into_sorted_stable_ord(), drop_order, } } diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 719d85ed3db..c56a028321a 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -473,7 +473,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner); let fcx_coercion_casts = fcx_typeck_results.coercion_casts().to_sorted_stable_ord(); - for local_id in fcx_coercion_casts { + for &local_id in fcx_coercion_casts { self.typeck_results.set_coercion_cast(local_id); } } diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs index bdc935a5e3b..08b7d08bcc0 100644 --- a/compiler/rustc_incremental/src/persist/save.rs +++ b/compiler/rustc_incremental/src/persist/save.rs @@ -103,7 +103,7 @@ pub fn save_work_product_index( // deleted during invalidation. Some object files don't change their // content, they are just not needed anymore. let previous_work_products = dep_graph.previous_work_products(); - for (id, wp) in previous_work_products.to_sorted_stable_ord().iter() { + for (id, wp) in previous_work_products.to_sorted_stable_ord() { if !new_work_products.contains_key(id) { work_product::delete_workproduct_files(sess, wp); debug_assert!( diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index a25cfe68e0d..eed35326c45 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -9,7 +9,9 @@ pub use self::Level::*; use rustc_ast::node_id::NodeId; use rustc_ast::{AttrId, Attribute}; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; +use rustc_data_structures::stable_hasher::{ + HashStable, StableCompare, StableHasher, ToStableHashKey, +}; use rustc_error_messages::{DiagnosticMessage, MultiSpan}; use rustc_hir::HashStableContext; use rustc_hir::HirId; @@ -541,6 +543,14 @@ impl ToStableHashKey for LintId { } } +impl StableCompare for LintId { + const CAN_USE_UNSTABLE_SORT: bool = true; + + fn stable_cmp(&self, other: &Self) -> std::cmp::Ordering { + self.lint_name_raw().cmp(&other.lint_name_raw()) + } +} + #[derive(Debug)] pub struct AmbiguityErrorDiag { pub msg: String, diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 58699c934b6..ad41a674dd8 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -527,7 +527,7 @@ impl<'a, V> LocalTableInContext<'a, V> { } pub fn items_in_stable_order(&self) -> Vec<(ItemLocalId, &'a V)> { - self.data.to_sorted_stable_ord() + self.data.items().map(|(&k, v)| (k, v)).into_sorted_stable_ord_by_key(|(k, _)| k) } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 0b44071496e..d8d24851620 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -4,7 +4,9 @@ use rustc_arena::DroplessArena; use rustc_data_structures::fx::FxIndexSet; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; +use rustc_data_structures::stable_hasher::{ + HashStable, StableCompare, StableHasher, ToStableHashKey, +}; use rustc_data_structures::sync::Lock; use rustc_macros::HashStable_Generic; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; @@ -2103,6 +2105,14 @@ impl ToStableHashKey for Symbol { } } +impl StableCompare for Symbol { + const CAN_USE_UNSTABLE_SORT: bool = true; + + fn stable_cmp(&self, other: &Self) -> std::cmp::Ordering { + self.as_str().cmp(other.as_str()) + } +} + pub(crate) struct Interner(Lock); // The `&'static str`s in this type actually point into the arena. From db132c575d1950c84d58009db922b6cbfe7a1918 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 21 Dec 2023 10:52:27 +0100 Subject: [PATCH 02/14] Replace a number of FxHashMaps/Sets with stable-iteration-order alternatives. --- .../rustc_hir_analysis/src/astconv/errors.rs | 5 +++-- compiler/rustc_hir_analysis/src/collect.rs | 3 ++- compiler/rustc_lint/src/foreign_modules.rs | 10 +++++----- compiler/rustc_lint/src/non_ascii_idents.rs | 11 ++++++----- compiler/rustc_metadata/src/rmeta/encoder.rs | 5 +++-- compiler/rustc_middle/src/middle/mod.rs | 15 ++++++++------- compiler/rustc_middle/src/middle/stability.rs | 3 ++- compiler/rustc_middle/src/query/mod.rs | 4 ++-- compiler/rustc_passes/src/stability.rs | 17 +++++++++-------- 9 files changed, 40 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index f17f19bb77c..7254f066dce 100644 --- a/compiler/rustc_hir_analysis/src/astconv/errors.rs +++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs @@ -6,6 +6,7 @@ use crate::errors::{ use crate::fluent_generated as fluent; use crate::traits::error_reporting::report_object_safety_error; use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet}; +use rustc_data_structures::unord::UnordMap; use rustc_errors::{pluralize, struct_span_err, Applicability, Diagnostic, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -673,7 +674,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { })) }) .flatten() - .collect::>(); + .collect::>(); let mut names = names .into_iter() @@ -709,7 +710,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut where_constraints = vec![]; let mut already_has_generics_args_suggestion = false; for (span, assoc_items) in &associated_types { - let mut names: FxHashMap<_, usize> = FxHashMap::default(); + let mut names: UnordMap<_, usize> = Default::default(); for item in assoc_items { types_count += 1; *names.entry(item.name).or_insert(0) += 1; diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 8aeab2ca67e..0a13949a688 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -16,6 +16,7 @@ use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::unord::UnordMap; use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey}; use rustc_hir as hir; use rustc_hir::def::DefKind; @@ -979,7 +980,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef { }) // Check for duplicates .and_then(|list| { - let mut set: FxHashMap = FxHashMap::default(); + let mut set: UnordMap = Default::default(); let mut no_dups = true; for ident in &*list { diff --git a/compiler/rustc_lint/src/foreign_modules.rs b/compiler/rustc_lint/src/foreign_modules.rs index 31d9c0d33fe..ecb7a157f39 100644 --- a/compiler/rustc_lint/src/foreign_modules.rs +++ b/compiler/rustc_lint/src/foreign_modules.rs @@ -1,5 +1,5 @@ -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stack::ensure_sufficient_stack; +use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_middle::query::Providers; @@ -72,7 +72,7 @@ struct ClashingExternDeclarations { /// the symbol should be reported as a clashing declaration. // FIXME: Technically, we could just store a &'tcx str here without issue; however, the // `impl_lint_pass` macro doesn't currently support lints parametric over a lifetime. - seen_decls: FxHashMap, + seen_decls: UnordMap, } /// Differentiate between whether the name for an extern decl came from the link_name attribute or @@ -96,7 +96,7 @@ impl SymbolName { impl ClashingExternDeclarations { pub(crate) fn new() -> Self { - ClashingExternDeclarations { seen_decls: FxHashMap::default() } + ClashingExternDeclarations { seen_decls: Default::default() } } /// Insert a new foreign item into the seen set. If a symbol with the same name already exists @@ -209,12 +209,12 @@ fn structurally_same_type<'tcx>( b: Ty<'tcx>, ckind: types::CItemKind, ) -> bool { - let mut seen_types = FxHashSet::default(); + let mut seen_types = UnordSet::default(); structurally_same_type_impl(&mut seen_types, tcx, param_env, a, b, ckind) } fn structurally_same_type_impl<'tcx>( - seen_types: &mut FxHashSet<(Ty<'tcx>, Ty<'tcx>)>, + seen_types: &mut UnordSet<(Ty<'tcx>, Ty<'tcx>)>, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, a: Ty<'tcx>, diff --git a/compiler/rustc_lint/src/non_ascii_idents.rs b/compiler/rustc_lint/src/non_ascii_idents.rs index 08b2bf6af37..3405dd3a916 100644 --- a/compiler/rustc_lint/src/non_ascii_idents.rs +++ b/compiler/rustc_lint/src/non_ascii_idents.rs @@ -4,7 +4,8 @@ use crate::lints::{ }; use crate::{EarlyContext, EarlyLintPass, LintContext}; use rustc_ast as ast; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::FxIndexMap; +use rustc_data_structures::unord::UnordMap; use rustc_span::symbol::Symbol; declare_lint! { @@ -194,8 +195,8 @@ impl EarlyLintPass for NonAsciiIdents { } if has_non_ascii_idents && check_confusable_idents { - let mut skeleton_map: FxHashMap = - FxHashMap::with_capacity_and_hasher(symbols.len(), Default::default()); + let mut skeleton_map: UnordMap = + UnordMap::with_capacity(symbols.len()); let mut skeleton_buf = String::new(); for (&symbol, &sp) in symbols.iter() { @@ -248,8 +249,8 @@ impl EarlyLintPass for NonAsciiIdents { Verified, } - let mut script_states: FxHashMap = - FxHashMap::default(); + let mut script_states: FxIndexMap = + Default::default(); let latin_augmented_script_set = AugmentedScriptSet::for_char('A'); script_states.insert(latin_augmented_script_set, ScriptSetUsage::Verified); diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 5b296c098bc..d761439f4ef 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1914,14 +1914,15 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { empty_proc_macro!(self); let tcx = self.tcx; let lib_features = tcx.lib_features(LOCAL_CRATE); - self.lazy_array(lib_features.to_vec()) + self.lazy_array(lib_features.to_sorted_vec()) } fn encode_stability_implications(&mut self) -> LazyArray<(Symbol, Symbol)> { empty_proc_macro!(self); let tcx = self.tcx; let implications = tcx.stability_implications(LOCAL_CRATE); - self.lazy_array(implications.iter().map(|(k, v)| (*k, *v))) + let sorted = implications.to_sorted_stable_ord(); + self.lazy_array(sorted.into_iter().map(|(k, v)| (*k, *v))) } fn encode_diagnostic_items(&mut self) -> LazyArray<(Symbol, DefIndex)> { diff --git a/compiler/rustc_middle/src/middle/mod.rs b/compiler/rustc_middle/src/middle/mod.rs index 8c1b1ff12e9..bdb2270611a 100644 --- a/compiler/rustc_middle/src/middle/mod.rs +++ b/compiler/rustc_middle/src/middle/mod.rs @@ -4,7 +4,7 @@ pub mod dependency_format; pub mod exported_symbols; pub mod lang_items; pub mod lib_features { - use rustc_data_structures::fx::FxHashMap; + use rustc_data_structures::unord::UnordMap; use rustc_span::{symbol::Symbol, Span}; #[derive(Copy, Clone, Debug, PartialEq, Eq)] @@ -16,15 +16,16 @@ pub mod lib_features { #[derive(HashStable, Debug, Default)] pub struct LibFeatures { - pub stability: FxHashMap, + pub stability: UnordMap, } impl LibFeatures { - pub fn to_vec(&self) -> Vec<(Symbol, FeatureStability)> { - let mut all_features: Vec<_> = - self.stability.iter().map(|(&sym, &(stab, _))| (sym, stab)).collect(); - all_features.sort_unstable_by(|(a, _), (b, _)| a.as_str().cmp(b.as_str())); - all_features + pub fn to_sorted_vec(&self) -> Vec<(Symbol, FeatureStability)> { + self.stability + .to_sorted_stable_ord() + .iter() + .map(|(&sym, &(stab, _))| (sym, stab)) + .collect() } } } diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index b2d1124b2ed..04b5af4d8a7 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -9,6 +9,7 @@ use rustc_attr::{ self as attr, ConstStability, DefaultBodyStability, DeprecatedSince, Deprecation, Stability, }; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::unord::UnordMap; use rustc_errors::{Applicability, Diagnostic}; use rustc_feature::GateIssue; use rustc_hir::def::DefKind; @@ -77,7 +78,7 @@ pub struct Index { /// to know that the feature implies another feature. If it were reversed, and the `#[stable]` /// attribute had an `implies` meta item, then a map would be necessary when avoiding a "use of /// unstable feature" error for a feature that was implied. - pub implications: FxHashMap, + pub implications: UnordMap, } impl Index { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 3a54f5f6b3d..ea807e31acf 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -61,7 +61,7 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet}; use rustc_data_structures::steal::Steal; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::Lrc; -use rustc_data_structures::unord::UnordSet; +use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_hir::def::{DefKind, DocLinkResMap}; @@ -1739,7 +1739,7 @@ rustc_queries! { separate_provide_extern arena_cache } - query stability_implications(_: CrateNum) -> &'tcx FxHashMap { + query stability_implications(_: CrateNum) -> &'tcx UnordMap { arena_cache desc { "calculating the implications between `#[unstable]` features defined in a crate" } separate_provide_extern diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 87fdedc15ba..adf4c231f78 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -6,7 +6,8 @@ use rustc_attr::{ self as attr, ConstStability, DeprecatedSince, Stability, StabilityLevel, StableSince, Unstable, UnstableReason, VERSION_PLACEHOLDER, }; -use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; +use rustc_data_structures::fx::FxIndexMap; +use rustc_data_structures::unord::{ExtendUnord, UnordMap, UnordSet}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{LocalDefId, LocalModDefId, CRATE_DEF_ID, LOCAL_CRATE}; @@ -923,7 +924,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { } let declared_lang_features = &tcx.features().declared_lang_features; - let mut lang_features = FxHashSet::default(); + let mut lang_features = UnordSet::default(); for &(feature, span, since) in declared_lang_features { if let Some(since) = since { // Warn if the user has enabled an already-stable lang feature. @@ -980,11 +981,11 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { fn check_features<'tcx>( tcx: TyCtxt<'tcx>, remaining_lib_features: &mut FxIndexMap<&Symbol, Span>, - remaining_implications: &mut FxHashMap, + remaining_implications: &mut UnordMap, defined_features: &LibFeatures, - all_implications: &FxHashMap, + all_implications: &UnordMap, ) { - for (feature, since) in defined_features.to_vec() { + for (feature, since) in defined_features.to_sorted_vec() { if let FeatureStability::AcceptedSince(since) = since && let Some(span) = remaining_lib_features.get(&feature) { @@ -1021,7 +1022,8 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { // `remaining_lib_features`. let mut all_implications = remaining_implications.clone(); for &cnum in tcx.crates(()) { - all_implications.extend(tcx.stability_implications(cnum)); + all_implications + .extend_unord(tcx.stability_implications(cnum).items().map(|(k, v)| (*k, *v))); } check_features( @@ -1052,8 +1054,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { // We only use the hash map contents to emit errors, and the order of // emitted errors do not affect query stability. - #[allow(rustc::potential_query_instability)] - for (implied_by, feature) in remaining_implications { + for (&implied_by, &feature) in remaining_implications.to_sorted_stable_ord() { let local_defined_features = tcx.lib_features(LOCAL_CRATE); let span = local_defined_features .stability From 138cfab9f7af26a7871fc0c3cff0888b1a9a7c3a Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 21 Dec 2023 11:10:30 +0100 Subject: [PATCH 03/14] Make iteration order of crate_inherent_impls query result stable. --- compiler/rustc_metadata/src/rmeta/encoder.rs | 12 +++--------- compiler/rustc_middle/src/ty/mod.rs | 3 ++- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index d761439f4ef..1d12b853b53 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -2,10 +2,8 @@ use crate::errors::{FailCreateFileEncoder, FailWriteFile}; use crate::rmeta::*; use rustc_ast::Attribute; -use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::memmap::{Mmap, MmapMut}; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{join, par_for_each_in, Lrc}; use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_hir as hir; @@ -2034,14 +2032,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_incoherent_impls(&mut self) -> LazyArray { empty_proc_macro!(self); let tcx = self.tcx; - let mut all_impls: Vec<_> = tcx.crate_inherent_impls(()).incoherent_impls.iter().collect(); - tcx.with_stable_hashing_context(|mut ctx| { - all_impls.sort_by_cached_key(|&(&simp, _)| { - let mut hasher = StableHasher::new(); - simp.hash_stable(&mut ctx, &mut hasher); - hasher.finish::() - }) + let all_impls = tcx.with_stable_hashing_context(|hcx| { + tcx.crate_inherent_impls(()).incoherent_impls.to_sorted(&hcx, true) }); + let all_impls: Vec<_> = all_impls .into_iter() .map(|(&simp, impls)| { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 757d3337afc..1ba9d56df7c 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -38,6 +38,7 @@ use rustc_data_structures::intern::Interned; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::steal::Steal; use rustc_data_structures::tagged_ptr::CopyTaggedPtr; +use rustc_data_structures::unord::UnordMap; use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, StashKey}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res}; @@ -2658,7 +2659,7 @@ pub fn provide(providers: &mut Providers) { #[derive(Clone, Debug, Default, HashStable)] pub struct CrateInherentImpls { pub inherent_impls: LocalDefIdMap>, - pub incoherent_impls: FxHashMap>, + pub incoherent_impls: UnordMap>, } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, HashStable)] From 0e934190fde43b6d03e5018e9d58c4924255fde9 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 21 Dec 2023 11:12:01 +0100 Subject: [PATCH 04/14] Make iteration order of upstream_monomorphizations query stable --- compiler/rustc_codegen_ssa/src/back/symbol_export.rs | 8 ++++---- compiler/rustc_middle/src/query/mod.rs | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 54b523cb6bd..0ff6a0c77d7 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -3,7 +3,7 @@ use crate::base::allocator_kind_for_codegen; use std::collections::hash_map::Entry::*; use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE}; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::unord::UnordMap; use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; @@ -393,10 +393,10 @@ fn exported_symbols_provider_local( fn upstream_monomorphizations_provider( tcx: TyCtxt<'_>, (): (), -) -> DefIdMap, CrateNum>> { +) -> DefIdMap, CrateNum>> { let cnums = tcx.crates(()); - let mut instances: DefIdMap> = Default::default(); + let mut instances: DefIdMap> = Default::default(); let drop_in_place_fn_def_id = tcx.lang_items().drop_in_place_fn(); @@ -445,7 +445,7 @@ fn upstream_monomorphizations_provider( fn upstream_monomorphizations_for_provider( tcx: TyCtxt<'_>, def_id: DefId, -) -> Option<&FxHashMap, CrateNum>> { +) -> Option<&UnordMap, CrateNum>> { debug_assert!(!def_id.is_local()); tcx.upstream_monomorphizations(()).get(&def_id) } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index ea807e31acf..31b1ad10510 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1542,7 +1542,7 @@ rustc_queries! { /// added or removed in any upstream crate. Instead use the narrower /// `upstream_monomorphizations_for`, `upstream_drop_glue_for`, or, even /// better, `Instance::upstream_monomorphization()`. - query upstream_monomorphizations(_: ()) -> &'tcx DefIdMap, CrateNum>> { + query upstream_monomorphizations(_: ()) -> &'tcx DefIdMap, CrateNum>> { arena_cache desc { "collecting available upstream monomorphizations" } } @@ -1555,7 +1555,7 @@ rustc_queries! { /// You likely want to call `Instance::upstream_monomorphization()` /// instead of invoking this query directly. query upstream_monomorphizations_for(def_id: DefId) - -> Option<&'tcx FxHashMap, CrateNum>> + -> Option<&'tcx UnordMap, CrateNum>> { desc { |tcx| "collecting available upstream monomorphizations for `{}`", From 02c7717ba6695f870fa3d9d306949efa178b1f1c Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 21 Dec 2023 11:12:37 +0100 Subject: [PATCH 05/14] Make iteration order of inferred_outlives_crate query stable --- compiler/rustc_middle/src/ty/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 1ba9d56df7c..4af82f12471 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -656,7 +656,7 @@ pub struct CratePredicatesMap<'tcx> { /// For each struct with outlive bounds, maps to a vector of the /// predicate of its outlive bounds. If an item has no outlives /// bounds, it will have no entry. - pub predicates: FxHashMap, Span)]>, + pub predicates: DefIdMap<&'tcx [(Clause<'tcx>, Span)]>, } impl<'tcx> Clause<'tcx> { From 762e21f8c1664339cfd17eaabc0c229945c1be9f Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 21 Dec 2023 11:13:03 +0100 Subject: [PATCH 06/14] Make iteration order of wasm_import_module_map query stable --- compiler/rustc_codegen_ssa/src/back/symbol_export.rs | 6 +++--- compiler/rustc_middle/src/query/mod.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 0ff6a0c77d7..94841ab7b33 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -656,7 +656,7 @@ fn maybe_emutls_symbol_name<'tcx>( } } -fn wasm_import_module_map(tcx: TyCtxt<'_>, cnum: CrateNum) -> FxHashMap { +fn wasm_import_module_map(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap { // Build up a map from DefId to a `NativeLib` structure, where // `NativeLib` internally contains information about // `#[link(wasm_import_module = "...")]` for example. @@ -665,9 +665,9 @@ fn wasm_import_module_map(tcx: TyCtxt<'_>, cnum: CrateNum) -> FxHashMap>(); + .collect::>(); - let mut ret = FxHashMap::default(); + let mut ret = DefIdMap::default(); for (def_id, lib) in tcx.foreign_modules(cnum).iter() { let module = def_id_to_native_lib.get(def_id).and_then(|s| s.wasm_import_module()); let Some(module) = module else { continue }; diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 31b1ad10510..855574512bf 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -611,7 +611,7 @@ rustc_queries! { desc { "erasing regions from `{}`", ty } } - query wasm_import_module_map(_: CrateNum) -> &'tcx FxHashMap { + query wasm_import_module_map(_: CrateNum) -> &'tcx DefIdMap { arena_cache desc { "getting wasm import module map" } } From d189d3efbc097a36e8d91cf94768ffc87c1b50bb Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 21 Dec 2023 11:18:03 +0100 Subject: [PATCH 07/14] Make iteration order of stability_index query stable --- compiler/rustc_middle/src/middle/stability.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index 04b5af4d8a7..90b479cf2f4 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -8,12 +8,11 @@ use rustc_ast::NodeId; use rustc_attr::{ self as attr, ConstStability, DefaultBodyStability, DeprecatedSince, Deprecation, Stability, }; -use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::unord::UnordMap; use rustc_errors::{Applicability, Diagnostic}; use rustc_feature::GateIssue; use rustc_hir::def::DefKind; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdMap}; use rustc_hir::{self as hir, HirId}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE, SOFT_UNSTABLE}; @@ -62,10 +61,10 @@ impl DeprecationEntry { pub struct Index { /// This is mostly a cache, except the stabilities of local items /// are filled by the annotator. - pub stab_map: FxHashMap, - pub const_stab_map: FxHashMap, - pub default_body_stab_map: FxHashMap, - pub depr_map: FxHashMap, + pub stab_map: LocalDefIdMap, + pub const_stab_map: LocalDefIdMap, + pub default_body_stab_map: LocalDefIdMap, + pub depr_map: LocalDefIdMap, /// Mapping from feature name to feature name based on the `implied_by` field of `#[unstable]` /// attributes. If a `#[unstable(feature = "implier", implied_by = "impliee")]` attribute /// exists, then this map will have a `impliee -> implier` entry. From d4a4c1dd28469eb874d7d1c7a95bc9e25c67a286 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 21 Dec 2023 11:30:01 +0100 Subject: [PATCH 08/14] Make iteration order of named_variable_map, late_bound_vars_map, and resolve_bound_vars queries stable --- compiler/rustc_middle/src/middle/resolve_bound_vars.rs | 6 +++--- compiler/rustc_middle/src/query/mod.rs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_middle/src/middle/resolve_bound_vars.rs b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs index c59704fc023..610afd95f3c 100644 --- a/compiler/rustc_middle/src/middle/resolve_bound_vars.rs +++ b/compiler/rustc_middle/src/middle/resolve_bound_vars.rs @@ -2,7 +2,7 @@ use crate::ty; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::FxIndexMap; use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::DefId; use rustc_hir::{ItemLocalId, OwnerId}; @@ -51,7 +51,7 @@ pub enum ObjectLifetimeDefault { pub struct ResolveBoundVars { /// Maps from every use of a named (not anonymous) lifetime to a /// `Region` describing how that region is bound - pub defs: FxHashMap>, + pub defs: FxIndexMap>, - pub late_bound_vars: FxHashMap>>, + pub late_bound_vars: FxIndexMap>>, } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 855574512bf..be10c7029e3 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1667,7 +1667,7 @@ rustc_queries! { desc { "resolving lifetimes" } } query named_variable_map(_: hir::OwnerId) -> - Option<&'tcx FxHashMap> { + Option<&'tcx FxIndexMap> { desc { "looking up a named region" } } query is_late_bound_map(_: hir::OwnerId) -> Option<&'tcx FxIndexSet> { @@ -1683,7 +1683,7 @@ rustc_queries! { separate_provide_extern } query late_bound_vars_map(_: hir::OwnerId) - -> Option<&'tcx FxHashMap>> { + -> Option<&'tcx FxIndexMap>> { desc { "looking up late bound vars" } } From 36dd3d4524ee6a0362f0866559e8289887406b83 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 21 Dec 2023 11:35:15 +0100 Subject: [PATCH 09/14] Make iteration order of region_scope_tree query stable --- compiler/rustc_middle/src/middle/region.rs | 29 +++------------------- compiler/rustc_span/src/def_id.rs | 18 +++++++++++++- 2 files changed, 21 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs index b4dd8f6f4a7..5d6a7f75df8 100644 --- a/compiler/rustc_middle/src/middle/region.rs +++ b/compiler/rustc_middle/src/middle/region.rs @@ -7,12 +7,11 @@ //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/borrow_check.html use crate::ty::TyCtxt; -use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::fx::FxIndexMap; +use rustc_data_structures::unord::UnordMap; use rustc_hir as hir; use rustc_hir::{HirIdMap, Node}; use rustc_macros::HashStable; -use rustc_query_system::ich::StableHashingContext; use rustc_span::{Span, DUMMY_SP}; use std::fmt; @@ -205,7 +204,7 @@ impl Scope { pub type ScopeDepth = u32; /// The region scope tree encodes information about region relationships. -#[derive(Default, Debug)] +#[derive(Default, Debug, HashStable)] pub struct ScopeTree { /// If not empty, this body is the root of this region hierarchy. pub root_body: Option, @@ -306,7 +305,7 @@ pub struct ScopeTree { /// The reason is that semantically, until the `box` expression returns, /// the values are still owned by their containing expressions. So /// we'll see that `&x`. - pub yield_in_scope: FxHashMap>, + pub yield_in_scope: UnordMap>, } /// Identifies the reason that a given expression is an rvalue candidate @@ -404,23 +403,3 @@ impl ScopeTree { self.yield_in_scope.get(&scope).map(Deref::deref) } } - -impl<'a> HashStable> for ScopeTree { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let ScopeTree { - root_body, - ref parent_map, - ref var_map, - ref destruction_scopes, - ref rvalue_candidates, - ref yield_in_scope, - } = *self; - - root_body.hash_stable(hcx, hasher); - parent_map.hash_stable(hcx, hasher); - var_map.hash_stable(hcx, hasher); - destruction_scopes.hash_stable(hcx, hasher); - rvalue_candidates.hash_stable(hcx, hasher); - yield_in_scope.hash_stable(hcx, hasher); - } -} diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs index e397fab5459..9f1db227a7c 100644 --- a/compiler/rustc_span/src/def_id.rs +++ b/compiler/rustc_span/src/def_id.rs @@ -1,6 +1,8 @@ use crate::{HashStableContext, Symbol}; use rustc_data_structures::fingerprint::Fingerprint; -use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher, ToStableHashKey}; +use rustc_data_structures::stable_hasher::{ + Hash64, HashStable, StableHasher, StableOrd, ToStableHashKey, +}; use rustc_data_structures::unhash::Unhasher; use rustc_data_structures::AtomicRef; use rustc_index::Idx; @@ -132,6 +134,11 @@ impl Default for DefPathHash { } } +// Safety: `DefPathHash` sort order is not affected (de)serialization. +unsafe impl StableOrd for DefPathHash { + const CAN_USE_UNSTABLE_SORT: bool = true; +} + /// A [`StableCrateId`] is a 64-bit hash of a crate name, together with all /// `-Cmetadata` arguments, and some other data. It is to [`CrateNum`] what [`DefPathHash`] is to /// [`DefId`]. It is stable across compilation sessions. @@ -490,6 +497,15 @@ impl ToStableHashKey for CrateNum { } } +impl ToStableHashKey for DefPathHash { + type KeyType = DefPathHash; + + #[inline] + fn to_stable_hash_key(&self, _: &CTX) -> DefPathHash { + *self + } +} + macro_rules! typed_def_id { ($Name:ident, $LocalName:ident) => { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Encodable, Decodable, HashStable_Generic)] From 7d4f2ee8172f065b20065ebbbf9ac9ee86a3c358 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 21 Dec 2023 12:27:04 +0100 Subject: [PATCH 10/14] Make iteration order of trimmed_def_paths query stable --- compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_middle/src/ty/print/pretty.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index be10c7029e3..553a57961f0 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1791,7 +1791,7 @@ rustc_queries! { } /// Collects the "trimmed", shortest accessible paths to all items for diagnostics. /// See the [provider docs](`rustc_middle::ty::print::trimmed_def_paths`) for more info. - query trimmed_def_paths(_: ()) -> &'tcx FxHashMap { + query trimmed_def_paths(_: ()) -> &'tcx DefIdMap { arena_cache desc { "calculating trimmed def paths" } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index ebbd02e01bf..7f11f59b5ee 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -12,7 +12,7 @@ use rustc_apfloat::Float; use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_hir as hir; use rustc_hir::def::{self, CtorKind, DefKind, Namespace}; -use rustc_hir::def_id::{DefIdSet, ModDefId, CRATE_DEF_ID, LOCAL_CRATE}; +use rustc_hir::def_id::{DefIdMap, DefIdSet, ModDefId, CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::definitions::{DefKey, DefPathDataName}; use rustc_hir::LangItem; use rustc_session::config::TrimmedDefPaths; @@ -3049,8 +3049,8 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N /// /// See also [`DelayDm`](rustc_error_messages::DelayDm) and [`with_no_trimmed_paths!`]. // this is pub to be able to intra-doc-link it -pub fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap { - let mut map: FxHashMap = FxHashMap::default(); +pub fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> DefIdMap { + let mut map: DefIdMap = Default::default(); if let TrimmedDefPaths::GoodPath = tcx.sess.opts.trimmed_def_paths { // Trimming paths is expensive and not optimized, since we expect it to only be used for error reporting. From 5449638d7d6b4f78b1f1fd6963eff35dd1a9705a Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 21 Dec 2023 12:30:36 +0100 Subject: [PATCH 11/14] Make iteration order of supported_target_features query stable --- compiler/rustc_codegen_ssa/src/target_features.rs | 4 ++-- compiler/rustc_middle/src/query/mod.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index 031fcc0adb1..b6bb1607a09 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -1,8 +1,8 @@ use crate::errors; use rustc_ast::ast; use rustc_attr::InstructionSetAttr; -use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxIndexSet; +use rustc_data_structures::unord::UnordMap; use rustc_errors::Applicability; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; @@ -18,7 +18,7 @@ use rustc_span::Span; pub fn from_target_feature( tcx: TyCtxt<'_>, attr: &ast::Attribute, - supported_target_features: &FxHashMap>, + supported_target_features: &UnordMap>, target_features: &mut Vec, ) { let Some(list) = attr.meta_item_list() else { return }; diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 553a57961f0..7b97593bdc8 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -2082,7 +2082,7 @@ rustc_queries! { desc { "computing autoderef types for `{}`", goal.value.value } } - query supported_target_features(_: CrateNum) -> &'tcx FxHashMap> { + query supported_target_features(_: CrateNum) -> &'tcx UnordMap> { arena_cache eval_always desc { "looking up supported target features" } From 5c8eee4275d7ee5ebf0871632ebc099c4e087e73 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 21 Dec 2023 14:21:01 +0100 Subject: [PATCH 12/14] Make iteration order of collect_return_position_impl_trait_in_trait_tys query stable --- compiler/rustc_hir_analysis/src/check/compare_impl_item.rs | 6 +++--- compiler/rustc_metadata/src/rmeta/mod.rs | 4 ++-- compiler/rustc_middle/src/arena.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 4 ++-- compiler/rustc_middle/src/query/on_disk_cache.rs | 4 ++-- compiler/rustc_middle/src/ty/parameterized.rs | 7 ++++--- 6 files changed, 14 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index dbcaa244f29..cc4dc5aca0d 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -1,6 +1,6 @@ use super::potentially_plural_count; use crate::errors::LifetimesOrBoundsMismatchOnTrait; -use hir::def_id::{DefId, LocalDefId}; +use hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed}; use rustc_hir as hir; @@ -478,7 +478,7 @@ fn compare_asyncness<'tcx>( pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( tcx: TyCtxt<'tcx>, impl_m_def_id: LocalDefId, -) -> Result<&'tcx FxHashMap>>, ErrorGuaranteed> { +) -> Result<&'tcx DefIdMap>>, ErrorGuaranteed> { let impl_m = tcx.opt_associated_item(impl_m_def_id.to_def_id()).unwrap(); let trait_m = tcx.opt_associated_item(impl_m.trait_item_def_id.unwrap()).unwrap(); let impl_trait_ref = @@ -706,7 +706,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( ); ocx.resolve_regions_and_report_errors(impl_m_def_id, &outlives_env)?; - let mut remapped_types = FxHashMap::default(); + let mut remapped_types = DefIdMap::default(); for (def_id, (ty, args)) in collected_types { match infcx.fully_resolve((ty, args)) { Ok((ty, args)) => { diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 54ee50c2358..2f775882693 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -12,7 +12,7 @@ use rustc_attr as attr; use rustc_data_structures::svh::Svh; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, DocLinkResMap}; -use rustc_hir::def_id::{CrateNum, DefId, DefIndex, DefPathHash, StableCrateId}; +use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIndex, DefPathHash, StableCrateId}; use rustc_hir::definitions::DefKey; use rustc_hir::lang_items::LangItem; use rustc_index::bit_set::BitSet; @@ -459,7 +459,7 @@ define_tables! { macro_definition: Table>, proc_macro: Table, deduced_param_attrs: Table>, - trait_impl_trait_tys: Table>>>>, + trait_impl_trait_tys: Table>>>>, doc_link_resolutions: Table>, doc_link_traits_in_scope: Table>, assumed_wf_types_for_rpitit: Table, Span)>>, diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index 52fd494a10d..0ab09dadf58 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -103,7 +103,7 @@ macro_rules! arena_types { [] dep_kind: rustc_middle::dep_graph::DepKindStruct<'tcx>, [decode] trait_impl_trait_tys: - rustc_data_structures::fx::FxHashMap< + rustc_data_structures::unord::UnordMap< rustc_hir::def_id::DefId, rustc_middle::ty::EarlyBinder> >, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 7b97593bdc8..08eac36bbb9 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -57,7 +57,7 @@ use rustc_ast as ast; use rustc_ast::expand::{allocator::AllocatorKind, StrippedCfgItem}; use rustc_attr as attr; use rustc_data_structures::fingerprint::Fingerprint; -use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet}; +use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::steal::Steal; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::Lrc; @@ -264,7 +264,7 @@ rustc_queries! { } query collect_return_position_impl_trait_in_trait_tys(key: DefId) - -> Result<&'tcx FxHashMap>>, ErrorGuaranteed> + -> Result<&'tcx DefIdMap>>, ErrorGuaranteed> { desc { "comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process" } cache_on_disk_if { key.is_local() } diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index 0577d22d850..8abf4a9e341 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -2,7 +2,7 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, RwLock}; use rustc_data_structures::unhash::UnhashMap; -use rustc_data_structures::unord::UnordSet; +use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, StableCrateId, LOCAL_CRATE}; use rustc_hir::definitions::DefPathHash; use rustc_index::{Idx, IndexVec}; @@ -764,7 +764,7 @@ impl<'a, 'tcx> Decodable> for &'tcx UnordSet } impl<'a, 'tcx> Decodable> - for &'tcx FxHashMap>> + for &'tcx UnordMap>> { #[inline] fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self { diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index a63a4eff5e1..47f9d9e61ad 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -1,6 +1,7 @@ -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::unord::UnordMap; use rustc_hir::def_id::DefIndex; use rustc_index::{Idx, IndexVec}; +use std::hash::Hash; use crate::ty; @@ -24,8 +25,8 @@ impl ParameterizedOverTcx for IndexVe type Value<'tcx> = IndexVec>; } -impl ParameterizedOverTcx for FxHashMap { - type Value<'tcx> = FxHashMap>; +impl ParameterizedOverTcx for UnordMap { + type Value<'tcx> = UnordMap>; } impl ParameterizedOverTcx for ty::Binder<'static, T> { From 900a11bbec52fdae89012ccb3ea4045edddc3995 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 22 Dec 2023 10:46:28 +0100 Subject: [PATCH 13/14] Provide generalized collect methods for UnordItems --- compiler/rustc_data_structures/src/unord.rs | 74 +++++++++++++-------- 1 file changed, 45 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_data_structures/src/unord.rs b/compiler/rustc_data_structures/src/unord.rs index 2475713012d..476ea432a0c 100644 --- a/compiler/rustc_data_structures/src/unord.rs +++ b/compiler/rustc_data_structures/src/unord.rs @@ -3,9 +3,8 @@ //! as required by the query system. use rustc_hash::{FxHashMap, FxHashSet}; -use smallvec::SmallVec; use std::{ - borrow::Borrow, + borrow::{Borrow, BorrowMut}, collections::hash_map::Entry, hash::Hash, iter::{Product, Sum}, @@ -135,13 +134,12 @@ impl<'a, T: Copy + 'a, I: Iterator> UnordItems<&'a T, I> { } impl> UnordItems { + #[inline] pub fn into_sorted(self, hcx: &HCX) -> Vec where T: ToStableHashKey, { - let mut items: Vec = self.0.collect(); - items.sort_by_cached_key(|x| x.to_stable_hash_key(hcx)); - items + self.collect_sorted(hcx, true) } #[inline] @@ -149,13 +147,7 @@ impl> UnordItems { where T: StableCompare, { - let mut items: Vec = self.0.collect(); - if !T::CAN_USE_UNSTABLE_SORT { - items.sort_by(T::stable_cmp); - } else { - items.sort_unstable_by(T::stable_cmp) - } - items + self.collect_stable_ord_by_key(|x| x) } #[inline] @@ -164,29 +156,53 @@ impl> UnordItems { K: StableCompare, C: for<'a> Fn(&'a T) -> &'a K, { - let mut items: Vec = self.0.collect(); - if !K::CAN_USE_UNSTABLE_SORT { - items.sort_by(|a, b| { - let a_key = project_to_key(a); - let b_key = project_to_key(b); - a_key.stable_cmp(b_key) - }); - } else { - items.sort_unstable_by(|a, b| { - let a_key = project_to_key(a); - let b_key = project_to_key(b); - a_key.stable_cmp(b_key) - }); + self.collect_stable_ord_by_key(project_to_key) + } + + pub fn collect_sorted(self, hcx: &HCX, cache_sort_key: bool) -> C + where + T: ToStableHashKey, + C: FromIterator + BorrowMut<[T]>, + { + let mut items: C = self.0.collect(); + + let slice = items.borrow_mut(); + if slice.len() > 1 { + if cache_sort_key { + slice.sort_by_cached_key(|x| x.to_stable_hash_key(hcx)); + } else { + slice.sort_by_key(|x| x.to_stable_hash_key(hcx)); + } } + items } - pub fn into_sorted_small_vec(self, hcx: &HCX) -> SmallVec<[T; LEN]> + pub fn collect_stable_ord_by_key(self, project_to_key: P) -> C where - T: ToStableHashKey, + K: StableCompare, + P: for<'a> Fn(&'a T) -> &'a K, + C: FromIterator + BorrowMut<[T]>, { - let mut items: SmallVec<[T; LEN]> = self.0.collect(); - items.sort_by_cached_key(|x| x.to_stable_hash_key(hcx)); + let mut items: C = self.0.collect(); + + let slice = items.borrow_mut(); + if slice.len() > 1 { + if !K::CAN_USE_UNSTABLE_SORT { + slice.sort_by(|a, b| { + let a_key = project_to_key(a); + let b_key = project_to_key(b); + a_key.stable_cmp(b_key) + }); + } else { + slice.sort_unstable_by(|a, b| { + let a_key = project_to_key(a); + let b_key = project_to_key(b); + a_key.stable_cmp(b_key) + }); + } + } + items } } From 077540cedf836b3c6e17db39de21e2278bae90fc Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 4 Jan 2024 13:51:06 +0100 Subject: [PATCH 14/14] Address review comments and add back some #[inline] attrs from removed commits. --- compiler/rustc_data_structures/src/unord.rs | 2 ++ compiler/rustc_passes/src/stability.rs | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_data_structures/src/unord.rs b/compiler/rustc_data_structures/src/unord.rs index 476ea432a0c..bd4dff6f62f 100644 --- a/compiler/rustc_data_structures/src/unord.rs +++ b/compiler/rustc_data_structures/src/unord.rs @@ -159,6 +159,7 @@ impl> UnordItems { self.collect_stable_ord_by_key(project_to_key) } + #[inline] pub fn collect_sorted(self, hcx: &HCX, cache_sort_key: bool) -> C where T: ToStableHashKey, @@ -178,6 +179,7 @@ impl> UnordItems { items } + #[inline] pub fn collect_stable_ord_by_key(self, project_to_key: P) -> C where K: StableCompare, diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index adf4c231f78..18b9ba0f042 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -1052,8 +1052,6 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { tcx.dcx().emit_err(errors::UnknownFeature { span, feature: *feature }); } - // We only use the hash map contents to emit errors, and the order of - // emitted errors do not affect query stability. for (&implied_by, &feature) in remaining_implications.to_sorted_stable_ord() { let local_defined_features = tcx.lib_features(LOCAL_CRATE); let span = local_defined_features