From 609f6493e0234f67db56c9fe7eab637336ee82f2 Mon Sep 17 00:00:00 2001
From: Hameer Abbasi <einstein.edison@gmail.com>
Date: Sun, 20 Feb 2022 16:35:57 +0100
Subject: [PATCH 1/4] Modify StableSet with a HashStable implementation.

---
 .../src/stable_hasher.rs                      | 15 +-------
 .../rustc_data_structures/src/stable_set.rs   | 34 +++++++++++++++++--
 2 files changed, 32 insertions(+), 17 deletions(-)

diff --git a/compiler/rustc_data_structures/src/stable_hasher.rs b/compiler/rustc_data_structures/src/stable_hasher.rs
index e8d81d4b937ab..6502a123d4523 100644
--- a/compiler/rustc_data_structures/src/stable_hasher.rs
+++ b/compiler/rustc_data_structures/src/stable_hasher.rs
@@ -544,19 +544,6 @@ where
     }
 }
 
-impl<K, R, HCX> HashStable<HCX> for ::std::collections::HashSet<K, R>
-where
-    K: ToStableHashKey<HCX> + Eq,
-    R: BuildHasher,
-{
-    fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
-        stable_hash_reduce(hcx, hasher, self.iter(), self.len(), |hasher, hcx, key| {
-            let key = key.to_stable_hash_key(hcx);
-            key.hash_stable(hcx, hasher);
-        });
-    }
-}
-
 impl<K, V, HCX> HashStable<HCX> for ::std::collections::BTreeMap<K, V>
 where
     K: ToStableHashKey<HCX>,
@@ -583,7 +570,7 @@ where
     }
 }
 
-fn stable_hash_reduce<HCX, I, C, F>(
+pub fn stable_hash_reduce<HCX, I, C, F>(
     hcx: &mut HCX,
     hasher: &mut StableHasher,
     mut collection: C,
diff --git a/compiler/rustc_data_structures/src/stable_set.rs b/compiler/rustc_data_structures/src/stable_set.rs
index c7ca74f5fbd9d..6f9d1df35fe89 100644
--- a/compiler/rustc_data_structures/src/stable_set.rs
+++ b/compiler/rustc_data_structures/src/stable_set.rs
@@ -3,6 +3,8 @@ use std::borrow::Borrow;
 use std::fmt;
 use std::hash::Hash;
 
+use crate::stable_hasher::{stable_hash_reduce, HashStable, StableHasher, ToStableHashKey};
+
 /// A deterministic wrapper around FxHashSet that does not provide iteration support.
 ///
 /// It supports insert, remove, get functions from FxHashSet.
@@ -16,6 +18,7 @@ impl<T> Default for StableSet<T>
 where
     T: Eq + Hash,
 {
+    #[inline]
     fn default() -> StableSet<T> {
         StableSet::new()
     }
@@ -25,6 +28,7 @@ impl<T> fmt::Debug for StableSet<T>
 where
     T: Eq + Hash + fmt::Debug,
 {
+    #[inline]
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "{:?}", self.base)
     }
@@ -34,6 +38,7 @@ impl<T> PartialEq<StableSet<T>> for StableSet<T>
 where
     T: Eq + Hash,
 {
+    #[inline]
     fn eq(&self, other: &StableSet<T>) -> bool {
         self.base == other.base
     }
@@ -42,19 +47,22 @@ where
 impl<T> Eq for StableSet<T> where T: Eq + Hash {}
 
 impl<T: Hash + Eq> StableSet<T> {
+    #[inline]
     pub fn new() -> StableSet<T> {
         StableSet { base: FxHashSet::default() }
     }
 
-    pub fn into_sorted_vector(self) -> Vec<T>
+    #[inline]
+    pub fn into_sorted_vector<HCX>(self, hcx: &HCX) -> Vec<T>
     where
-        T: Ord,
+        T: ToStableHashKey<HCX>,
     {
         let mut vector = self.base.into_iter().collect::<Vec<_>>();
-        vector.sort_unstable();
+        vector.sort_by_cached_key(|x| x.to_stable_hash_key(hcx));
         vector
     }
 
+    #[inline]
     pub fn get<Q: ?Sized>(&self, value: &Q) -> Option<&T>
     where
         T: Borrow<Q>,
@@ -63,10 +71,12 @@ impl<T: Hash + Eq> StableSet<T> {
         self.base.get(value)
     }
 
+    #[inline]
     pub fn insert(&mut self, value: T) -> bool {
         self.base.insert(value)
     }
 
+    #[inline]
     pub fn remove<Q: ?Sized>(&mut self, value: &Q) -> bool
     where
         T: Borrow<Q>,
@@ -74,4 +84,22 @@ impl<T: Hash + Eq> StableSet<T> {
     {
         self.base.remove(value)
     }
+
+    #[inline]
+    pub fn contains(&self, value: &T) -> bool {
+        self.base.contains(value)
+    }
+}
+
+impl<T, HCX> HashStable<HCX> for StableSet<T>
+where
+    T: ToStableHashKey<HCX> + Eq,
+{
+    #[inline]
+    fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
+        stable_hash_reduce(hcx, hasher, self.base.iter(), self.base.len(), |hasher, hcx, key| {
+            let key = key.to_stable_hash_key(hcx);
+            key.hash_stable(hcx, hasher);
+        });
+    }
 }

From 72c9dd7c806ca2ce9c05512151ac1a5dd571c52c Mon Sep 17 00:00:00 2001
From: Hameer Abbasi <einstein.edison@gmail.com>
Date: Sun, 20 Feb 2022 16:36:22 +0100
Subject: [PATCH 2/4] Attempt at replacing all occurrences.

---
 compiler/rustc_codegen_ssa/src/base.rs        |  2 +-
 compiler/rustc_data_structures/src/fx.rs      |  2 +-
 .../rustc_data_structures/src/stable_set.rs   | 39 +++++++++++++++++--
 compiler/rustc_metadata/src/rmeta/encoder.rs  |  2 +-
 compiler/rustc_middle/src/middle/mod.rs       | 11 ++++--
 .../src/middle/resolve_lifetime.rs            |  5 ++-
 compiler/rustc_middle/src/middle/stability.rs |  9 ++++-
 compiler/rustc_middle/src/query/mod.rs        | 12 +++---
 compiler/rustc_middle/src/ty/context.rs       |  7 ++--
 compiler/rustc_middle/src/ty/mod.rs           |  3 +-
 compiler/rustc_middle/src/ty/print/pretty.rs  |  3 +-
 compiler/rustc_middle/src/ty/query.rs         |  5 ++-
 compiler/rustc_passes/src/stability.rs        |  2 +-
 compiler/rustc_resolve/src/late/lifetimes.rs  |  7 ++--
 compiler/rustc_resolve/src/lib.rs             |  3 +-
 compiler/rustc_typeck/src/check/mod.rs        |  2 +-
 compiler/rustc_typeck/src/check/writeback.rs  |  3 +-
 17 files changed, 85 insertions(+), 32 deletions(-)

diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 010560248054e..f7dae40efb2af 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -910,7 +910,7 @@ pub fn provide(providers: &mut Providers) {
         };
 
         let (defids, _) = tcx.collect_and_partition_mono_items(cratenum);
-        for id in &*defids {
+        for id in defids.sorted_vector() {
             let CodegenFnAttrs { optimize, .. } = tcx.codegen_fn_attrs(*id);
             match optimize {
                 attr::OptimizeAttr::None => continue,
diff --git a/compiler/rustc_data_structures/src/fx.rs b/compiler/rustc_data_structures/src/fx.rs
index bbeb193dba32b..584ef7bdb1d82 100644
--- a/compiler/rustc_data_structures/src/fx.rs
+++ b/compiler/rustc_data_structures/src/fx.rs
@@ -9,6 +9,6 @@ pub type FxIndexSet<V> = indexmap::IndexSet<V, BuildHasherDefault<FxHasher>>;
 macro_rules! define_id_collections {
     ($map_name:ident, $set_name:ident, $key:ty) => {
         pub type $map_name<T> = $crate::fx::FxHashMap<$key, T>;
-        pub type $set_name = $crate::fx::FxHashSet<$key>;
+        pub type $set_name = $crate::stable_set::StableSet<$key>;
     };
 }
diff --git a/compiler/rustc_data_structures/src/stable_set.rs b/compiler/rustc_data_structures/src/stable_set.rs
index 6f9d1df35fe89..abb4c9c594e40 100644
--- a/compiler/rustc_data_structures/src/stable_set.rs
+++ b/compiler/rustc_data_structures/src/stable_set.rs
@@ -9,8 +9,11 @@ use crate::stable_hasher::{stable_hash_reduce, HashStable, StableHasher, ToStabl
 ///
 /// It supports insert, remove, get functions from FxHashSet.
 /// It also allows to convert hashset to a sorted vector with the method `into_sorted_vector()`.
-#[derive(Clone)]
-pub struct StableSet<T> {
+#[derive(Clone, Encodable, Decodable)]
+pub struct StableSet<T>
+where
+    T: Eq + Hash,
+{
     base: FxHashSet<T>,
 }
 
@@ -62,6 +65,16 @@ impl<T: Hash + Eq> StableSet<T> {
         vector
     }
 
+    #[inline]
+    pub fn sorted_vector<HCX>(&self, hcx: &HCX) -> Vec<&T>
+    where
+        T: ToStableHashKey<HCX>,
+    {
+        let mut vector = self.base.iter().collect::<Vec<_>>();
+        vector.sort_by_cached_key(|x| x.to_stable_hash_key(hcx));
+        vector
+    }
+
     #[inline]
     pub fn get<Q: ?Sized>(&self, value: &Q) -> Option<&T>
     where
@@ -93,7 +106,7 @@ impl<T: Hash + Eq> StableSet<T> {
 
 impl<T, HCX> HashStable<HCX> for StableSet<T>
 where
-    T: ToStableHashKey<HCX> + Eq,
+    T: ToStableHashKey<HCX> + Eq + Hash,
 {
     #[inline]
     fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
@@ -103,3 +116,23 @@ where
         });
     }
 }
+
+impl<T> FromIterator<T> for StableSet<T>
+where
+    T: Eq + Hash,
+{
+    #[inline]
+    fn from_iter<Collection: IntoIterator<Item = T>>(iter: Collection) -> Self {
+        Self { base: iter.into_iter().collect() }
+    }
+}
+
+impl<T> Extend<T> for StableSet<T>
+where
+    T: Eq + Hash,
+{
+    #[inline]
+    fn extend<Iter: IntoIterator<Item = T>>(&mut self, iter: Iter) {
+        self.base.extend(iter)
+    }
+}
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 6c758b8e5b633..ee1ba04f4332d 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1742,7 +1742,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         empty_proc_macro!(self);
         let tcx = self.tcx;
         let lib_features = tcx.lib_features(());
-        self.lazy(lib_features.to_vec())
+        self.lazy(lib_features.to_vec(tcx))
     }
 
     fn encode_diagnostic_items(&mut self) -> Lazy<[(Symbol, DefIndex)]> {
diff --git a/compiler/rustc_middle/src/middle/mod.rs b/compiler/rustc_middle/src/middle/mod.rs
index fc35cafcc77a1..dfc30477e5cdf 100644
--- a/compiler/rustc_middle/src/middle/mod.rs
+++ b/compiler/rustc_middle/src/middle/mod.rs
@@ -3,23 +3,26 @@ pub mod dependency_format;
 pub mod exported_symbols;
 pub mod lang_items;
 pub mod lib_features {
-    use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+    use rustc_data_structures::{fx::FxHashMap, stable_set::StableSet};
     use rustc_span::symbol::Symbol;
 
+    use crate::ty::TyCtxt;
+
     #[derive(HashStable, Debug)]
     pub struct LibFeatures {
         // A map from feature to stabilisation version.
         pub stable: FxHashMap<Symbol, Symbol>,
-        pub unstable: FxHashSet<Symbol>,
+        pub unstable: StableSet<Symbol>,
     }
 
     impl LibFeatures {
-        pub fn to_vec(&self) -> Vec<(Symbol, Option<Symbol>)> {
+        pub fn to_vec(&self, tcx: TyCtxt<'_>) -> Vec<(Symbol, Option<Symbol>)> {
+            let hcx = tcx.create_stable_hashing_context();
             let mut all_features: Vec<_> = self
                 .stable
                 .iter()
                 .map(|(f, s)| (*f, Some(*s)))
-                .chain(self.unstable.iter().map(|f| (*f, None)))
+                .chain(self.unstable.sorted_vector(&hcx).into_iter().map(|f| (*f, None)))
                 .collect();
             all_features.sort_unstable_by(|a, b| a.0.as_str().partial_cmp(b.0.as_str()).unwrap());
             all_features
diff --git a/compiler/rustc_middle/src/middle/resolve_lifetime.rs b/compiler/rustc_middle/src/middle/resolve_lifetime.rs
index 98375cbad9f9b..92dd97c4b3d79 100644
--- a/compiler/rustc_middle/src/middle/resolve_lifetime.rs
+++ b/compiler/rustc_middle/src/middle/resolve_lifetime.rs
@@ -2,7 +2,8 @@
 
 use crate::ty;
 
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::stable_set::StableSet;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::ItemLocalId;
 use rustc_macros::HashStable;
@@ -63,7 +64,7 @@ pub struct ResolveLifetimes {
     /// Set of lifetime def ids that are late-bound; a region can
     /// be late-bound if (a) it does NOT appear in a where-clause and
     /// (b) it DOES appear in the arguments.
-    pub late_bound: FxHashMap<LocalDefId, FxHashSet<ItemLocalId>>,
+    pub late_bound: FxHashMap<LocalDefId, StableSet<ItemLocalId>>,
 
     pub late_bound_vars: FxHashMap<LocalDefId, FxHashMap<ItemLocalId, Vec<ty::BoundVariableKind>>>,
 }
diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs
index fd6e241346db8..e9c9e25f2a0bc 100644
--- a/compiler/rustc_middle/src/middle/stability.rs
+++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -7,12 +7,13 @@ use crate::ty::{self, DefIdTree, TyCtxt};
 use rustc_ast::NodeId;
 use rustc_attr::{self as attr, ConstStability, Deprecation, Stability};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::stable_set::StableSet;
 use rustc_errors::{Applicability, Diagnostic};
 use rustc_feature::GateIssue;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX};
-use rustc_hir::{self, HirId};
+use rustc_hir::{self, def_id::CrateNum, HirId};
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE, SOFT_UNSTABLE};
 use rustc_session::lint::{BuiltinLintDiagnostics, Level, Lint, LintBuffer};
@@ -63,6 +64,12 @@ pub struct Index {
     pub stab_map: FxHashMap<LocalDefId, Stability>,
     pub const_stab_map: FxHashMap<LocalDefId, ConstStability>,
     pub depr_map: FxHashMap<LocalDefId, DeprecationEntry>,
+
+    /// Maps for each crate whether it is part of the staged API.
+    pub staged_api: FxHashMap<CrateNum, bool>,
+
+    /// Features enabled for this crate.
+    pub active_features: StableSet<Symbol>,
 }
 
 impl Index {
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 89761bf4e27a0..5a4ab611505c5 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -775,7 +775,7 @@ rustc_queries! {
     /// The second return value maps from ADTs to ignored derived traits (e.g. Debug and Clone) and
     /// their respective impl (i.e., part of the derive macro)
     query live_symbols_and_ignored_derived_traits(_: ()) -> (
-        FxHashSet<LocalDefId>,
+        StableSet<LocalDefId>,
         FxHashMap<LocalDefId, Vec<(DefId, DefId)>>
     ) {
         storage(ArenaCacheSelector<'tcx>)
@@ -828,7 +828,7 @@ rustc_queries! {
         }
     }
 
-    query used_trait_imports(key: LocalDefId) -> &'tcx FxHashSet<LocalDefId> {
+    query used_trait_imports(key: LocalDefId) -> &'tcx StableSet<LocalDefId> {
         desc { |tcx| "used_trait_imports `{}`", tcx.def_path_str(key.to_def_id()) }
         cache_on_disk_if { true }
     }
@@ -978,7 +978,7 @@ rustc_queries! {
         desc { "checking for private elements in public interfaces" }
     }
 
-    query reachable_set(_: ()) -> FxHashSet<LocalDefId> {
+    query reachable_set(_: ()) -> StableSet<LocalDefId> {
         storage(ArenaCacheSelector<'tcx>)
         desc { "reachability" }
     }
@@ -1055,7 +1055,7 @@ rustc_queries! {
         cache_on_disk_if { true }
     }
 
-    query asm_target_features(def_id: DefId) -> &'tcx FxHashSet<Symbol> {
+    query asm_target_features(def_id: DefId) -> &'tcx StableSet<Symbol> {
         desc { |tcx| "computing target features for inline asm of `{}`", tcx.def_path_str(def_id) }
     }
 
@@ -1506,7 +1506,7 @@ rustc_queries! {
         desc { "looking up a named region" }
     }
     query is_late_bound_map(_: LocalDefId) ->
-        Option<(LocalDefId, &'tcx FxHashSet<ItemLocalId>)> {
+        Option<(LocalDefId, &'tcx StableSet<ItemLocalId>)> {
         desc { "testing if a region is late bound" }
     }
     /// For a given item (like a struct), gets the default lifetimes to be used
@@ -1645,7 +1645,7 @@ rustc_queries! {
     query maybe_unused_extern_crates(_: ()) -> &'tcx [(LocalDefId, Span)] {
         desc { "looking up all possibly unused extern crates" }
     }
-    query names_imported_by_glob_use(def_id: LocalDefId) -> &'tcx FxHashSet<Symbol> {
+    query names_imported_by_glob_use(def_id: LocalDefId) -> &'tcx StableSet<Symbol> {
         desc { |tcx| "names_imported_by_glob_use for `{}`", tcx.def_path_str(def_id.to_def_id()) }
     }
 
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 6ca8f8b1309fa..946b8863ccaa9 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -25,12 +25,13 @@ use crate::ty::{
 };
 use rustc_ast as ast;
 use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::intern::Interned;
 use rustc_data_structures::memmap::Mmap;
 use rustc_data_structures::profiling::SelfProfilerRef;
 use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::stable_set::StableSet;
 use rustc_data_structures::steal::Steal;
 use rustc_data_structures::sync::{self, Lock, Lrc, WorkerLocal};
 use rustc_data_structures::vec_map::VecMap;
@@ -480,7 +481,7 @@ pub struct TypeckResults<'tcx> {
     /// This is used for warning unused imports. During type
     /// checking, this `Lrc` should not be cloned: it must have a ref-count
     /// of 1 so that we can insert things into the set mutably.
-    pub used_trait_imports: Lrc<FxHashSet<LocalDefId>>,
+    pub used_trait_imports: Lrc<StableSet<LocalDefId>>,
 
     /// If any errors occurred while type-checking this body,
     /// this field will be set to `Some(ErrorGuaranteed)`.
@@ -2208,7 +2209,7 @@ impl<'tcx> TyCtxt<'tcx> {
     /// to identify which traits may define a given associated type to help avoid cycle errors.
     /// Returns a `DefId` iterator.
     fn super_traits_of(self, trait_def_id: DefId) -> impl Iterator<Item = DefId> + 'tcx {
-        let mut set = FxHashSet::default();
+        let mut set = StableSet::default();
         let mut stack = vec![trait_def_id];
 
         set.insert(trait_def_id);
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 6e3dc92a2332f..413bfd472120e 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -18,6 +18,7 @@ pub use adt::*;
 pub use assoc::*;
 pub use generics::*;
 use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_data_structures::stable_set::StableSet;
 pub use vtable::*;
 
 use crate::metadata::ModChild;
@@ -135,7 +136,7 @@ pub struct ResolverOutputs {
     pub maybe_unused_trait_imports: FxHashSet<LocalDefId>,
     pub maybe_unused_extern_crates: Vec<(LocalDefId, Span)>,
     pub reexport_map: FxHashMap<LocalDefId, Vec<ModChild>>,
-    pub glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>,
+    pub glob_map: FxHashMap<LocalDefId, StableSet<Symbol>>,
     /// Extern prelude entries. The value is `true` if the entry was introduced
     /// via `extern crate` item and not `--extern` option or compiler built-in.
     pub extern_prelude: FxHashMap<Symbol, bool>,
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 9a9c529f24552..d396473890530 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -2763,8 +2763,9 @@ fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap<DefId, Symbol> {
     let unique_symbols_rev: &mut FxHashMap<(Namespace, Symbol), Option<DefId>> =
         &mut FxHashMap::default();
 
+    let hcx = tcx.create_stable_hashing_context();
     for symbol_set in tcx.resolutions(()).glob_map.values() {
-        for symbol in symbol_set {
+        for symbol in symbol_set.sorted_vector(&hcx) {
             unique_symbols_rev.insert((Namespace::TypeNS, *symbol), None);
             unique_symbols_rev.insert((Namespace::ValueNS, *symbol), None);
             unique_symbols_rev.insert((Namespace::MacroNS, *symbol), None);
diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs
index 9e48c569c253a..5008b487d643b 100644
--- a/compiler/rustc_middle/src/ty/query.rs
+++ b/compiler/rustc_middle/src/ty/query.rs
@@ -33,10 +33,13 @@ use crate::ty::subst::{GenericArg, SubstsRef};
 use crate::ty::util::AlwaysRequiresDrop;
 use crate::ty::{self, AdtSizedConstraint, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt};
 use rustc_ast::expand::allocator::AllocatorKind;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
 use rustc_data_structures::steal::Steal;
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::{
+    fx::{FxHashMap, FxIndexMap},
+    stable_set::StableSet,
+};
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index 84b4a803403f9..00ed3f4d7964f 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -898,7 +898,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
 
     // We always collect the lib features declared in the current crate, even if there are
     // no unknown features, because the collection also does feature attribute validation.
-    let local_defined_features = tcx.lib_features(()).to_vec();
+    let local_defined_features = tcx.lib_features(()).to_vec(tcx);
     if !remaining_lib_features.is_empty() {
         check_features(&mut remaining_lib_features, &local_defined_features);
 
diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs
index afb19d7df9fce..00c44f1ee7108 100644
--- a/compiler/rustc_resolve/src/late/lifetimes.rs
+++ b/compiler/rustc_resolve/src/late/lifetimes.rs
@@ -8,6 +8,7 @@
 
 use crate::late::diagnostics::{ForLifetimeSpanType, MissingLifetimeSpot};
 use rustc_ast::walk_list;
+use rustc_ast_lowering::ResolverAstLowering;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
 use rustc_errors::{struct_span_err, Applicability, Diagnostic};
 use rustc_hir as hir;
@@ -468,14 +469,14 @@ fn do_resolve(
     named_region_map
 }
 
-fn convert_named_region_map(named_region_map: NamedRegionMap) -> ResolveLifetimes {
+fn convert_named_region_map(named_region_map: NamedRegionMap, tcx: TyCtxt<'_>) -> ResolveLifetimes {
     let mut rl = ResolveLifetimes::default();
-
+    let hcx = tcx.create_stable_hashing_context();
     for (hir_id, v) in named_region_map.defs {
         let map = rl.defs.entry(hir_id.owner).or_default();
         map.insert(hir_id.local_id, v);
     }
-    for hir_id in named_region_map.late_bound {
+    for hir_id in named_region_map.late_bound.sorted_vector(&hcx) {
         let map = rl.late_bound.entry(hir_id.owner).or_default();
         map.insert(hir_id.local_id);
     }
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index a09a225a2b5d7..f239ec1a9a9ea 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -24,6 +24,7 @@
 #[macro_use]
 extern crate tracing;
 
+use rustc_data_structures::stable_set::StableSet;
 pub use rustc_hir::def::{Namespace, PerNS};
 
 use Determinacy::*;
@@ -975,7 +976,7 @@ pub struct Resolver<'a> {
     underscore_disambiguator: u32,
 
     /// Maps glob imports to the names of items actually imported.
-    glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>,
+    glob_map: FxHashMap<LocalDefId, StableSet<Symbol>>,
     /// Visibilities in "lowered" form, for all entities that have them.
     visibilities: FxHashMap<LocalDefId, ty::Visibility>,
     used_imports: FxHashSet<NodeId>,
diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs
index 19d52f430fcd5..e00fed5a74fd5 100644
--- a/compiler/rustc_typeck/src/check/mod.rs
+++ b/compiler/rustc_typeck/src/check/mod.rs
@@ -312,7 +312,7 @@ fn has_typeck_results(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
     }
 }
 
-fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &FxHashSet<LocalDefId> {
+fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &StableSet<LocalDefId> {
     &*tcx.typeck(def_id).used_trait_imports
 }
 
diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs
index 72a50d02ad88f..e4d2386af6dc7 100644
--- a/compiler/rustc_typeck/src/check/writeback.rs
+++ b/compiler/rustc_typeck/src/check/writeback.rs
@@ -425,8 +425,9 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         let fcx_typeck_results = self.fcx.typeck_results.borrow();
         let fcx_coercion_casts = fcx_typeck_results.coercion_casts();
         assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
+        let hcx = self.tcx().create_stable_hashing_context();
 
-        for local_id in fcx_coercion_casts {
+        for local_id in fcx_coercion_casts.sorted_vector(&hcx) {
             self.typeck_results.set_coercion_cast(*local_id);
         }
     }

From fb669bcb6d509030dfa041a24da6979306bb67a2 Mon Sep 17 00:00:00 2001
From: Hameer Abbasi <einstein.edison@gmail.com>
Date: Sun, 27 Mar 2022 16:07:00 +0200
Subject: [PATCH 3/4] Do some suggested changes, push to show compilation
 errors.

---
 compiler/rustc_codegen_ssa/src/base.rs           | 15 ++++++---------
 compiler/rustc_data_structures/src/stable_set.rs | 16 ++++++++++++++++
 compiler/rustc_middle/src/middle/stability.rs    |  9 +--------
 compiler/rustc_middle/src/ty/context.rs          |  4 ++--
 compiler/rustc_middle/src/ty/mod.rs              |  3 +--
 compiler/rustc_middle/src/ty/print/pretty.rs     |  2 +-
 6 files changed, 27 insertions(+), 22 deletions(-)

diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index f7dae40efb2af..4316555b1a95d 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -910,17 +910,14 @@ pub fn provide(providers: &mut Providers) {
         };
 
         let (defids, _) = tcx.collect_and_partition_mono_items(cratenum);
-        for id in defids.sorted_vector() {
+        if defids.any(|x| {
             let CodegenFnAttrs { optimize, .. } = tcx.codegen_fn_attrs(*id);
-            match optimize {
-                attr::OptimizeAttr::None => continue,
-                attr::OptimizeAttr::Size => continue,
-                attr::OptimizeAttr::Speed => {
-                    return for_speed;
-                }
-            }
+            optimize == attr::OptimizeAttr::Speed
+        }) {
+            for_speed
+        } else {
+            tcx.sess.opts.optimize
         }
-        tcx.sess.opts.optimize
     };
 }
 
diff --git a/compiler/rustc_data_structures/src/stable_set.rs b/compiler/rustc_data_structures/src/stable_set.rs
index abb4c9c594e40..4b6b0c3e168d8 100644
--- a/compiler/rustc_data_structures/src/stable_set.rs
+++ b/compiler/rustc_data_structures/src/stable_set.rs
@@ -102,6 +102,22 @@ impl<T: Hash + Eq> StableSet<T> {
     pub fn contains(&self, value: &T) -> bool {
         self.base.contains(value)
     }
+
+    #[inline]
+    pub fn any<F>(&self, f: F) -> bool
+    where
+        F: FnMut(&T) -> bool,
+    {
+        self.base.iter().any(f)
+    }
+
+    #[inline]
+    pub fn all<F>(&self, f: F) -> bool
+    where
+        F: FnMut(&T) -> bool,
+    {
+        self.base.iter().all(f)
+    }
 }
 
 impl<T, HCX> HashStable<HCX> for StableSet<T>
diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs
index e9c9e25f2a0bc..fd6e241346db8 100644
--- a/compiler/rustc_middle/src/middle/stability.rs
+++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -7,13 +7,12 @@ use crate::ty::{self, DefIdTree, TyCtxt};
 use rustc_ast::NodeId;
 use rustc_attr::{self as attr, ConstStability, Deprecation, Stability};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::stable_set::StableSet;
 use rustc_errors::{Applicability, Diagnostic};
 use rustc_feature::GateIssue;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX};
-use rustc_hir::{self, def_id::CrateNum, HirId};
+use rustc_hir::{self, HirId};
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE, SOFT_UNSTABLE};
 use rustc_session::lint::{BuiltinLintDiagnostics, Level, Lint, LintBuffer};
@@ -64,12 +63,6 @@ pub struct Index {
     pub stab_map: FxHashMap<LocalDefId, Stability>,
     pub const_stab_map: FxHashMap<LocalDefId, ConstStability>,
     pub depr_map: FxHashMap<LocalDefId, DeprecationEntry>,
-
-    /// Maps for each crate whether it is part of the staged API.
-    pub staged_api: FxHashMap<CrateNum, bool>,
-
-    /// Features enabled for this crate.
-    pub active_features: StableSet<Symbol>,
 }
 
 impl Index {
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 946b8863ccaa9..1f84bcd628883 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -31,7 +31,7 @@ use rustc_data_structures::memmap::Mmap;
 use rustc_data_structures::profiling::SelfProfilerRef;
 use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_data_structures::stable_set::StableSet;
+use rustc_data_structures::stable_set::{FxHashSet, StableSet};
 use rustc_data_structures::steal::Steal;
 use rustc_data_structures::sync::{self, Lock, Lrc, WorkerLocal};
 use rustc_data_structures::vec_map::VecMap;
@@ -2209,7 +2209,7 @@ impl<'tcx> TyCtxt<'tcx> {
     /// to identify which traits may define a given associated type to help avoid cycle errors.
     /// Returns a `DefId` iterator.
     fn super_traits_of(self, trait_def_id: DefId) -> impl Iterator<Item = DefId> + 'tcx {
-        let mut set = StableSet::default();
+        let mut set = FxHashSet::default();
         let mut stack = vec![trait_def_id];
 
         set.insert(trait_def_id);
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 413bfd472120e..6e3dc92a2332f 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -18,7 +18,6 @@ pub use adt::*;
 pub use assoc::*;
 pub use generics::*;
 use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_data_structures::stable_set::StableSet;
 pub use vtable::*;
 
 use crate::metadata::ModChild;
@@ -136,7 +135,7 @@ pub struct ResolverOutputs {
     pub maybe_unused_trait_imports: FxHashSet<LocalDefId>,
     pub maybe_unused_extern_crates: Vec<(LocalDefId, Span)>,
     pub reexport_map: FxHashMap<LocalDefId, Vec<ModChild>>,
-    pub glob_map: FxHashMap<LocalDefId, StableSet<Symbol>>,
+    pub glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>,
     /// Extern prelude entries. The value is `true` if the entry was introduced
     /// via `extern crate` item and not `--extern` option or compiler built-in.
     pub extern_prelude: FxHashMap<Symbol, bool>,
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index d396473890530..6065cdd3a4a88 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -2765,7 +2765,7 @@ fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap<DefId, Symbol> {
 
     let hcx = tcx.create_stable_hashing_context();
     for symbol_set in tcx.resolutions(()).glob_map.values() {
-        for symbol in symbol_set.sorted_vector(&hcx) {
+        for symbol in symbol_set {
             unique_symbols_rev.insert((Namespace::TypeNS, *symbol), None);
             unique_symbols_rev.insert((Namespace::ValueNS, *symbol), None);
             unique_symbols_rev.insert((Namespace::MacroNS, *symbol), None);

From d505d55ffbd109f73c01331f12662342d9ccdc81 Mon Sep 17 00:00:00 2001
From: Hameer Abbasi <einstein.edison@gmail.com>
Date: Fri, 8 Apr 2022 18:59:25 +0200
Subject: [PATCH 4/4] Add stable iteration API.

---
 compiler/rustc_data_structures/src/lib.rs     |  1 +
 .../src/stable_iterator.rs                    | 73 +++++++++++++++++++
 .../rustc_data_structures/src/stable_set.rs   | 43 +++++++----
 compiler/rustc_middle/src/ty/context.rs       |  4 +-
 compiler/rustc_middle/src/ty/print/pretty.rs  |  1 -
 compiler/rustc_resolve/src/late/lifetimes.rs  |  3 +-
 6 files changed, 107 insertions(+), 18 deletions(-)
 create mode 100644 compiler/rustc_data_structures/src/stable_iterator.rs

diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index 1a3fe65252156..a07714af785ad 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -87,6 +87,7 @@ pub mod svh;
 pub use ena::snapshot_vec;
 pub mod memmap;
 pub mod sorted_map;
+pub mod stable_iterator;
 pub mod stable_set;
 #[macro_use]
 pub mod stable_hasher;
diff --git a/compiler/rustc_data_structures/src/stable_iterator.rs b/compiler/rustc_data_structures/src/stable_iterator.rs
new file mode 100644
index 0000000000000..e6ef24e6c2a11
--- /dev/null
+++ b/compiler/rustc_data_structures/src/stable_iterator.rs
@@ -0,0 +1,73 @@
+use std::iter::Chain;
+
+use crate::stable_hasher::ToStableHashKey;
+
+pub struct StableIterator<I: Iterator> {
+    inner: I,
+}
+
+impl<T, I: Iterator<Item = T>> StableIterator<I> {
+    #[inline]
+    pub fn map<U, F: Fn(T) -> U>(self, f: F) -> StableIterator<impl Iterator<Item = U>> {
+        StableIterator { inner: self.inner.map(f) }
+    }
+
+    #[inline]
+    pub fn into_sorted<HCX>(self, hcx: &HCX) -> Vec<T>
+    where
+        T: ToStableHashKey<HCX>,
+    {
+        let mut items: Vec<T> = self.inner.collect();
+        items.sort_by_cached_key(|x| x.to_stable_hash_key(hcx));
+        items
+    }
+
+    #[inline]
+    pub fn any<F: Fn(T) -> bool>(&mut self, f: F) -> bool {
+        self.inner.any(f)
+    }
+
+    #[inline]
+    pub fn all<F: Fn(T) -> bool>(&mut self, f: F) -> bool {
+        self.inner.all(f)
+    }
+
+    #[inline]
+    pub fn chain<J: Iterator<Item = I::Item>>(self, other: StableIterator<J>) -> StableChain<I, J> {
+        self.inner.chain(other.inner).into()
+    }
+}
+
+pub trait IntoStableIterator {
+    type IntoIter: Iterator;
+    fn into_stable_iter(self) -> StableIterator<Self::IntoIter>;
+}
+
+impl<I: Iterator, S: IntoIterator<Item = I::Item, IntoIter = I>> IntoStableIterator for S {
+    type IntoIter = I;
+
+    #[inline]
+    fn into_stable_iter(self) -> StableIterator<I> {
+        StableIterator { inner: self.into_iter() }
+    }
+}
+
+pub struct StableChain<I: Iterator, J: Iterator> {
+    inner: Chain<I, J>,
+}
+
+impl<I: Iterator, J: Iterator<Item = I::Item>> IntoStableIterator for StableChain<I, J> {
+    type IntoIter = Chain<I, J>;
+
+    #[inline]
+    fn into_stable_iter(self) -> StableIterator<Self::IntoIter> {
+        self.inner.into_stable_iter()
+    }
+}
+
+impl<I: Iterator, J: Iterator> From<Chain<I, J>> for StableChain<I, J> {
+    #[inline]
+    fn from(inner: Chain<I, J>) -> Self {
+        Self { inner }
+    }
+}
diff --git a/compiler/rustc_data_structures/src/stable_set.rs b/compiler/rustc_data_structures/src/stable_set.rs
index 4b6b0c3e168d8..e777ec3920fe4 100644
--- a/compiler/rustc_data_structures/src/stable_set.rs
+++ b/compiler/rustc_data_structures/src/stable_set.rs
@@ -1,9 +1,11 @@
 pub use rustc_hash::FxHashSet;
 use std::borrow::Borrow;
+use std::collections::hash_set;
 use std::fmt;
 use std::hash::Hash;
 
 use crate::stable_hasher::{stable_hash_reduce, HashStable, StableHasher, ToStableHashKey};
+use crate::stable_iterator::{IntoStableIterator, StableIterator};
 
 /// A deterministic wrapper around FxHashSet that does not provide iteration support.
 ///
@@ -103,20 +105,8 @@ impl<T: Hash + Eq> StableSet<T> {
         self.base.contains(value)
     }
 
-    #[inline]
-    pub fn any<F>(&self, f: F) -> bool
-    where
-        F: FnMut(&T) -> bool,
-    {
-        self.base.iter().any(f)
-    }
-
-    #[inline]
-    pub fn all<F>(&self, f: F) -> bool
-    where
-        F: FnMut(&T) -> bool,
-    {
-        self.base.iter().all(f)
+    pub fn stable_iter<'a>(&'a self) -> StableIterator<hash_set::Iter<'a, T>> {
+        (&self).into_stable_iter()
     }
 }
 
@@ -143,6 +133,31 @@ where
     }
 }
 
+impl<T: Eq + Hash> IntoStableIterator for StableSet<T> {
+    type IntoIter = hash_set::IntoIter<T>;
+    #[inline]
+    fn into_stable_iter(self) -> StableIterator<Self::IntoIter> {
+        self.base.into_stable_iter()
+    }
+}
+
+impl<'a, T: Eq + Hash> IntoStableIterator for &'a StableSet<T> {
+    type IntoIter = hash_set::Iter<'a, T>;
+    #[inline]
+    fn into_stable_iter(self) -> StableIterator<Self::IntoIter> {
+        self.base.iter().into_stable_iter()
+    }
+}
+
+impl<T> From<FxHashSet<T>> for StableSet<T>
+where
+    T: Eq + Hash,
+{
+    fn from(base: FxHashSet<T>) -> Self {
+        Self { base: base }
+    }
+}
+
 impl<T> Extend<T> for StableSet<T>
 where
     T: Eq + Hash,
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 1f84bcd628883..2aac2ac73b0e8 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -2952,7 +2952,9 @@ pub fn provide(providers: &mut ty::query::Providers) {
     providers.maybe_unused_extern_crates =
         |tcx, ()| &tcx.resolutions(()).maybe_unused_extern_crates[..];
     providers.names_imported_by_glob_use = |tcx, id| {
-        tcx.arena.alloc(tcx.resolutions(()).glob_map.get(&id).cloned().unwrap_or_default())
+        &StableSet::from(
+            tcx.arena.alloc(tcx.resolutions(()).glob_map.get(&id).cloned().unwrap_or_default()),
+        )
     };
 
     providers.extern_mod_stmt_cnum =
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 6065cdd3a4a88..9a9c529f24552 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -2763,7 +2763,6 @@ fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> FxHashMap<DefId, Symbol> {
     let unique_symbols_rev: &mut FxHashMap<(Namespace, Symbol), Option<DefId>> =
         &mut FxHashMap::default();
 
-    let hcx = tcx.create_stable_hashing_context();
     for symbol_set in tcx.resolutions(()).glob_map.values() {
         for symbol in symbol_set {
             unique_symbols_rev.insert((Namespace::TypeNS, *symbol), None);
diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs
index 00c44f1ee7108..0bff85f531d72 100644
--- a/compiler/rustc_resolve/src/late/lifetimes.rs
+++ b/compiler/rustc_resolve/src/late/lifetimes.rs
@@ -469,9 +469,8 @@ fn do_resolve(
     named_region_map
 }
 
-fn convert_named_region_map(named_region_map: NamedRegionMap, tcx: TyCtxt<'_>) -> ResolveLifetimes {
+fn convert_named_region_map(named_region_map: NamedRegionMap) -> ResolveLifetimes {
     let mut rl = ResolveLifetimes::default();
-    let hcx = tcx.create_stable_hashing_context();
     for (hir_id, v) in named_region_map.defs {
         let map = rl.defs.entry(hir_id.owner).or_default();
         map.insert(hir_id.local_id, v);