diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 010560248054e..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 { + 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/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 = indexmap::IndexSet>; macro_rules! define_id_collections { ($map_name:ident, $set_name:ident, $key:ty) => { pub type $map_name = $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/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_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 HashStable for ::std::collections::HashSet -where - K: ToStableHashKey + 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 HashStable for ::std::collections::BTreeMap where K: ToStableHashKey, @@ -583,7 +570,7 @@ where } } -fn stable_hash_reduce( +pub fn stable_hash_reduce( hcx: &mut HCX, hasher: &mut StableHasher, mut collection: C, 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 { + inner: I, +} + +impl> StableIterator { + #[inline] + pub fn map U>(self, f: F) -> StableIterator> { + StableIterator { inner: self.inner.map(f) } + } + + #[inline] + pub fn into_sorted(self, hcx: &HCX) -> Vec + where + T: ToStableHashKey, + { + let mut items: Vec = self.inner.collect(); + items.sort_by_cached_key(|x| x.to_stable_hash_key(hcx)); + items + } + + #[inline] + pub fn any bool>(&mut self, f: F) -> bool { + self.inner.any(f) + } + + #[inline] + pub fn all bool>(&mut self, f: F) -> bool { + self.inner.all(f) + } + + #[inline] + pub fn chain>(self, other: StableIterator) -> StableChain { + self.inner.chain(other.inner).into() + } +} + +pub trait IntoStableIterator { + type IntoIter: Iterator; + fn into_stable_iter(self) -> StableIterator; +} + +impl> IntoStableIterator for S { + type IntoIter = I; + + #[inline] + fn into_stable_iter(self) -> StableIterator { + StableIterator { inner: self.into_iter() } + } +} + +pub struct StableChain { + inner: Chain, +} + +impl> IntoStableIterator for StableChain { + type IntoIter = Chain; + + #[inline] + fn into_stable_iter(self) -> StableIterator { + self.inner.into_stable_iter() + } +} + +impl From> for StableChain { + #[inline] + fn from(inner: Chain) -> Self { + Self { inner } + } +} diff --git a/compiler/rustc_data_structures/src/stable_set.rs b/compiler/rustc_data_structures/src/stable_set.rs index c7ca74f5fbd9d..e777ec3920fe4 100644 --- a/compiler/rustc_data_structures/src/stable_set.rs +++ b/compiler/rustc_data_structures/src/stable_set.rs @@ -1,14 +1,21 @@ 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. /// /// 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 { +#[derive(Clone, Encodable, Decodable)] +pub struct StableSet +where + T: Eq + Hash, +{ base: FxHashSet, } @@ -16,6 +23,7 @@ impl Default for StableSet where T: Eq + Hash, { + #[inline] fn default() -> StableSet { StableSet::new() } @@ -25,6 +33,7 @@ impl fmt::Debug for StableSet where T: Eq + Hash + fmt::Debug, { + #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}", self.base) } @@ -34,6 +43,7 @@ impl PartialEq> for StableSet where T: Eq + Hash, { + #[inline] fn eq(&self, other: &StableSet) -> bool { self.base == other.base } @@ -42,19 +52,32 @@ where impl Eq for StableSet where T: Eq + Hash {} impl StableSet { + #[inline] pub fn new() -> StableSet { StableSet { base: FxHashSet::default() } } - pub fn into_sorted_vector(self) -> Vec + #[inline] + pub fn into_sorted_vector(self, hcx: &HCX) -> Vec where - T: Ord, + T: ToStableHashKey, { let mut vector = self.base.into_iter().collect::>(); - vector.sort_unstable(); + vector.sort_by_cached_key(|x| x.to_stable_hash_key(hcx)); vector } + #[inline] + pub fn sorted_vector(&self, hcx: &HCX) -> Vec<&T> + where + T: ToStableHashKey, + { + let mut vector = self.base.iter().collect::>(); + vector.sort_by_cached_key(|x| x.to_stable_hash_key(hcx)); + vector + } + + #[inline] pub fn get(&self, value: &Q) -> Option<&T> where T: Borrow, @@ -63,10 +86,12 @@ impl StableSet { self.base.get(value) } + #[inline] pub fn insert(&mut self, value: T) -> bool { self.base.insert(value) } + #[inline] pub fn remove(&mut self, value: &Q) -> bool where T: Borrow, @@ -74,4 +99,71 @@ impl StableSet { { self.base.remove(value) } + + #[inline] + pub fn contains(&self, value: &T) -> bool { + self.base.contains(value) + } + + pub fn stable_iter<'a>(&'a self) -> StableIterator> { + (&self).into_stable_iter() + } +} + +impl HashStable for StableSet +where + T: ToStableHashKey + Eq + Hash, +{ + #[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); + }); + } +} + +impl FromIterator for StableSet +where + T: Eq + Hash, +{ + #[inline] + fn from_iter>(iter: Collection) -> Self { + Self { base: iter.into_iter().collect() } + } +} + +impl IntoStableIterator for StableSet { + type IntoIter = hash_set::IntoIter; + #[inline] + fn into_stable_iter(self) -> StableIterator { + self.base.into_stable_iter() + } +} + +impl<'a, T: Eq + Hash> IntoStableIterator for &'a StableSet { + type IntoIter = hash_set::Iter<'a, T>; + #[inline] + fn into_stable_iter(self) -> StableIterator { + self.base.iter().into_stable_iter() + } +} + +impl From> for StableSet +where + T: Eq + Hash, +{ + fn from(base: FxHashSet) -> Self { + Self { base: base } + } +} + +impl Extend for StableSet +where + T: Eq + Hash, +{ + #[inline] + fn extend>(&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, - pub unstable: FxHashSet, + pub unstable: StableSet, } impl LibFeatures { - pub fn to_vec(&self) -> Vec<(Symbol, Option)> { + pub fn to_vec(&self, tcx: TyCtxt<'_>) -> Vec<(Symbol, Option)> { + 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>, + pub late_bound: FxHashMap>, pub late_bound_vars: FxHashMap>>, } 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, + StableSet, FxHashMap> ) { storage(ArenaCacheSelector<'tcx>) @@ -828,7 +828,7 @@ rustc_queries! { } } - query used_trait_imports(key: LocalDefId) -> &'tcx FxHashSet { + query used_trait_imports(key: LocalDefId) -> &'tcx StableSet { 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 { + query reachable_set(_: ()) -> StableSet { 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 { + query asm_target_features(def_id: DefId) -> &'tcx StableSet { 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)> { + Option<(LocalDefId, &'tcx StableSet)> { 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 { + query names_imported_by_glob_use(def_id: LocalDefId) -> &'tcx StableSet { 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..2aac2ac73b0e8 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::{FxHashSet, 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>, + pub used_trait_imports: Lrc>, /// If any errors occurred while type-checking this body, /// this field will be set to `Some(ErrorGuaranteed)`. @@ -2951,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/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..0bff85f531d72 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; @@ -470,12 +471,11 @@ fn do_resolve( fn convert_named_region_map(named_region_map: NamedRegionMap) -> ResolveLifetimes { let mut rl = ResolveLifetimes::default(); - 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>, + glob_map: FxHashMap>, /// Visibilities in "lowered" form, for all entities that have them. visibilities: FxHashMap, used_imports: FxHashSet, 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 { +fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &StableSet { &*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); } }