From 144e576c87627a01dc6ab387f57a21a03659021d Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Tue, 23 Aug 2016 00:57:54 +0200 Subject: [PATCH 1/6] Use `FnvHashMap` in more places * A step towards #34902 * More stable error messages in some places related to crate loading * Possible slight performance improvements since all `HashMap`s replaced had small keys where `FnvHashMap` should be faster (although I didn't measure) --- src/librustc/infer/freshen.rs | 7 +-- src/librustc/middle/dead.rs | 12 ++--- src/librustc/middle/reachable.rs | 5 +- src/librustc_metadata/loader.rs | 14 +++--- src/librustc_metadata/macro_import.rs | 10 ++-- src/librustc_resolve/assign_ids.rs | 4 +- src/librustc_resolve/lib.rs | 49 +++++++++---------- src/librustc_trans/base.rs | 5 +- src/librustc_typeck/check/intrinsic.rs | 6 +-- src/librustc_typeck/check/method/probe.rs | 10 ++-- src/librustc_typeck/check/mod.rs | 7 ++- src/librustc_typeck/check/wfcheck.rs | 6 +-- src/librustc_typeck/collect.rs | 15 +++--- .../constrained_type_params.rs | 6 +-- 14 files changed, 76 insertions(+), 80 deletions(-) diff --git a/src/librustc/infer/freshen.rs b/src/librustc/infer/freshen.rs index beda734ee0d56..f793d489cab06 100644 --- a/src/librustc/infer/freshen.rs +++ b/src/librustc/infer/freshen.rs @@ -32,7 +32,8 @@ use ty::{self, Ty, TyCtxt, TypeFoldable}; use ty::fold::TypeFolder; -use std::collections::hash_map::{self, Entry}; +use util::nodemap::FnvHashMap; +use std::collections::hash_map::Entry; use super::InferCtxt; use super::unify_key::ToType; @@ -40,7 +41,7 @@ use super::unify_key::ToType; pub struct TypeFreshener<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, freshen_count: u32, - freshen_map: hash_map::HashMap>, + freshen_map: FnvHashMap>, } impl<'a, 'gcx, 'tcx> TypeFreshener<'a, 'gcx, 'tcx> { @@ -49,7 +50,7 @@ impl<'a, 'gcx, 'tcx> TypeFreshener<'a, 'gcx, 'tcx> { TypeFreshener { infcx: infcx, freshen_count: 0, - freshen_map: hash_map::HashMap::new(), + freshen_map: FnvHashMap(), } } diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 37366f38974a4..f44b149a84617 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -22,8 +22,8 @@ use ty::{self, TyCtxt}; use hir::def::Def; use hir::def_id::{DefId}; use lint; +use util::nodemap::FnvHashSet; -use std::collections::HashSet; use syntax::{ast, codemap}; use syntax::attr; use syntax_pos; @@ -48,7 +48,7 @@ fn should_explore<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, struct MarkSymbolVisitor<'a, 'tcx: 'a> { worklist: Vec, tcx: TyCtxt<'a, 'tcx, 'tcx>, - live_symbols: Box>, + live_symbols: Box>, struct_has_extern_repr: bool, ignore_non_const_paths: bool, inherited_pub_visibility: bool, @@ -61,7 +61,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { MarkSymbolVisitor { worklist: worklist, tcx: tcx, - live_symbols: box HashSet::new(), + live_symbols: box FnvHashSet(), struct_has_extern_repr: false, ignore_non_const_paths: false, inherited_pub_visibility: false, @@ -162,7 +162,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { } fn mark_live_symbols(&mut self) { - let mut scanned = HashSet::new(); + let mut scanned = FnvHashSet(); while !self.worklist.is_empty() { let id = self.worklist.pop().unwrap(); if scanned.contains(&id) { @@ -395,7 +395,7 @@ fn create_and_seed_worklist<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn find_live<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, access_levels: &privacy::AccessLevels, krate: &hir::Crate) - -> Box> { + -> Box> { let worklist = create_and_seed_worklist(tcx, access_levels, krate); let mut symbol_visitor = MarkSymbolVisitor::new(tcx, worklist); symbol_visitor.mark_live_symbols(); @@ -413,7 +413,7 @@ fn get_struct_ctor_id(item: &hir::Item) -> Option { struct DeadVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, - live_symbols: Box>, + live_symbols: Box>, } impl<'a, 'tcx> DeadVisitor<'a, 'tcx> { diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 6ea0fa20c5726..e29a7cf9d6846 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -22,9 +22,8 @@ use hir::def_id::DefId; use ty::{self, TyCtxt}; use middle::privacy; use session::config; -use util::nodemap::NodeSet; +use util::nodemap::{NodeSet, FnvHashSet}; -use std::collections::HashSet; use syntax::abi::Abi; use syntax::ast; use syntax::attr; @@ -204,7 +203,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { // Step 2: Mark all symbols that the symbols on the worklist touch. fn propagate(&mut self) { - let mut scanned = HashSet::new(); + let mut scanned = FnvHashSet(); loop { let search_item = match self.worklist.pop() { Some(item) => item, diff --git a/src/librustc_metadata/loader.rs b/src/librustc_metadata/loader.rs index 2345cd9a92aea..b2c87db8ef566 100644 --- a/src/librustc_metadata/loader.rs +++ b/src/librustc_metadata/loader.rs @@ -221,6 +221,7 @@ use rustc::session::Session; use rustc::session::filesearch::{FileSearch, FileMatches, FileDoesntMatch}; use rustc::session::search_paths::PathKind; use rustc::util::common; +use rustc::util::nodemap::FnvHashMap; use rustc_llvm as llvm; use rustc_llvm::{False, ObjectFile, mk_section_iter}; @@ -230,7 +231,6 @@ use syntax_pos::Span; use rustc_back::target::Target; use std::cmp; -use std::collections::HashMap; use std::fmt; use std::fs; use std::io; @@ -413,7 +413,7 @@ impl<'a> Context<'a> { let rlib_prefix = format!("lib{}", self.crate_name); let staticlib_prefix = format!("{}{}", staticpair.0, self.crate_name); - let mut candidates = HashMap::new(); + let mut candidates = FnvHashMap(); let mut staticlibs = vec!(); // First, find all possible candidate rlibs and dylibs purely based on @@ -456,7 +456,7 @@ impl<'a> Context<'a> { let hash_str = hash.to_string(); let slot = candidates.entry(hash_str) - .or_insert_with(|| (HashMap::new(), HashMap::new())); + .or_insert_with(|| (FnvHashMap(), FnvHashMap())); let (ref mut rlibs, ref mut dylibs) = *slot; fs::canonicalize(path).map(|p| { if rlib { @@ -477,7 +477,7 @@ impl<'a> Context<'a> { // A Library candidate is created if the metadata for the set of // libraries corresponds to the crate id and hash criteria that this // search is being performed for. - let mut libraries = HashMap::new(); + let mut libraries = FnvHashMap(); for (_hash, (rlibs, dylibs)) in candidates { let mut slot = None; let rlib = self.extract_one(rlibs, CrateFlavor::Rlib, &mut slot); @@ -527,7 +527,7 @@ impl<'a> Context<'a> { // read the metadata from it if `*slot` is `None`. If the metadata couldn't // be read, it is assumed that the file isn't a valid rust library (no // errors are emitted). - fn extract_one(&mut self, m: HashMap, flavor: CrateFlavor, + fn extract_one(&mut self, m: FnvHashMap, flavor: CrateFlavor, slot: &mut Option<(Svh, MetadataBlob)>) -> Option<(PathBuf, PathKind)> { let mut ret: Option<(PathBuf, PathKind)> = None; let mut error = 0; @@ -669,8 +669,8 @@ impl<'a> Context<'a> { // rlibs/dylibs. let sess = self.sess; let dylibname = self.dylibname(); - let mut rlibs = HashMap::new(); - let mut dylibs = HashMap::new(); + let mut rlibs = FnvHashMap(); + let mut dylibs = FnvHashMap(); { let locs = locs.map(|l| PathBuf::from(l)).filter(|loc| { if !loc.exists() { diff --git a/src/librustc_metadata/macro_import.rs b/src/librustc_metadata/macro_import.rs index b2a2dcf90fa4b..2cd60f04e69a1 100644 --- a/src/librustc_metadata/macro_import.rs +++ b/src/librustc_metadata/macro_import.rs @@ -14,8 +14,8 @@ use creader::CrateReader; use cstore::CStore; use rustc::session::Session; +use rustc::util::nodemap::{FnvHashSet, FnvHashMap}; -use std::collections::{HashSet, HashMap}; use syntax::parse::token; use syntax::ast; use syntax::attr; @@ -45,13 +45,13 @@ pub fn call_bad_macro_reexport(a: &Session, b: Span) { span_err!(a, b, E0467, "bad macro reexport"); } -pub type MacroSelection = HashMap; +pub type MacroSelection = FnvHashMap; impl<'a> ext::base::MacroLoader for MacroLoader<'a> { fn load_crate(&mut self, extern_crate: &ast::Item, allows_macros: bool) -> Vec { // Parse the attributes relating to macros. - let mut import = Some(HashMap::new()); // None => load all - let mut reexport = HashMap::new(); + let mut import = Some(FnvHashMap()); // None => load all + let mut reexport = FnvHashMap(); for attr in &extern_crate.attrs { let mut used = true; @@ -120,7 +120,7 @@ impl<'a> MacroLoader<'a> { } let mut macros = Vec::new(); - let mut seen = HashSet::new(); + let mut seen = FnvHashSet(); for mut def in self.reader.read_exported_macros(vi) { let name = def.ident.name.as_str(); diff --git a/src/librustc_resolve/assign_ids.rs b/src/librustc_resolve/assign_ids.rs index 70e566de8a7be..a9e3c6ffe9ed8 100644 --- a/src/librustc_resolve/assign_ids.rs +++ b/src/librustc_resolve/assign_ids.rs @@ -10,6 +10,7 @@ use Resolver; use rustc::session::Session; +use rustc::util::nodemap::FnvHashMap; use syntax::ast; use syntax::ext::hygiene::Mark; use syntax::fold::{self, Folder}; @@ -17,7 +18,6 @@ use syntax::ptr::P; use syntax::util::move_map::MoveMap; use syntax::util::small_vector::SmallVector; -use std::collections::HashMap; use std::mem; impl<'a> Resolver<'a> { @@ -31,7 +31,7 @@ impl<'a> Resolver<'a> { struct NodeIdAssigner<'a> { sess: &'a Session, - macros_at_scope: &'a mut HashMap>, + macros_at_scope: &'a mut FnvHashMap>, } impl<'a> Folder for NodeIdAssigner<'a> { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 5641a50ccaccf..6a4a48377c783 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -68,7 +68,6 @@ use syntax::ast::{PathSegment, PathParameters, QSelf, TraitItemKind, TraitRef, T use syntax_pos::Span; use errors::DiagnosticBuilder; -use std::collections::{HashMap, HashSet}; use std::cell::{Cell, RefCell}; use std::fmt; use std::mem::replace; @@ -498,7 +497,7 @@ struct BindingInfo { } // Map from the name in a pattern to its binding mode. -type BindingMap = HashMap; +type BindingMap = FnvHashMap; #[derive(Copy, Clone, PartialEq, Eq, Debug)] enum PatternSource { @@ -703,14 +702,14 @@ enum ModulePrefixResult<'a> { /// One local scope. #[derive(Debug)] struct Rib<'a> { - bindings: HashMap, + bindings: FnvHashMap, kind: RibKind<'a>, } impl<'a> Rib<'a> { fn new(kind: RibKind<'a>) -> Rib<'a> { Rib { - bindings: HashMap::new(), + bindings: FnvHashMap(), kind: kind, } } @@ -773,7 +772,7 @@ pub struct ModuleS<'a> { // is the NodeId of the local `extern crate` item (otherwise, `extern_crate_id` is None). extern_crate_id: Option, - resolutions: RefCell>>>, + resolutions: RefCell>>>, no_implicit_prelude: Cell, @@ -797,7 +796,7 @@ impl<'a> ModuleS<'a> { parent_link: parent_link, def: def, extern_crate_id: None, - resolutions: RefCell::new(HashMap::new()), + resolutions: RefCell::new(FnvHashMap()), no_implicit_prelude: Cell::new(false), glob_importers: RefCell::new(Vec::new()), globs: RefCell::new((Vec::new())), @@ -930,12 +929,12 @@ impl<'a> NameBinding<'a> { /// Interns the names of the primitive types. struct PrimitiveTypeTable { - primitive_types: HashMap, + primitive_types: FnvHashMap, } impl PrimitiveTypeTable { fn new() -> PrimitiveTypeTable { - let mut table = PrimitiveTypeTable { primitive_types: HashMap::new() }; + let mut table = PrimitiveTypeTable { primitive_types: FnvHashMap() }; table.intern("bool", TyBool); table.intern("char", TyChar); @@ -969,7 +968,7 @@ pub struct Resolver<'a> { // Maps the node id of a statement to the expansions of the `macro_rules!`s // immediately above the statement (if appropriate). - macros_at_scope: HashMap>, + macros_at_scope: FnvHashMap>, graph_root: Module<'a>, @@ -1043,8 +1042,8 @@ pub struct Resolver<'a> { // all imports, but only glob imports are actually interesting). pub glob_map: GlobMap, - used_imports: HashSet<(NodeId, Namespace)>, - used_crates: HashSet, + used_imports: FnvHashSet<(NodeId, Namespace)>, + used_crates: FnvHashSet, pub maybe_unused_trait_imports: NodeSet, privacy_errors: Vec>, @@ -1164,7 +1163,7 @@ impl<'a> Resolver<'a> { session: session, definitions: Definitions::new(), - macros_at_scope: HashMap::new(), + macros_at_scope: FnvHashMap(), // The outermost module has def ID 0; this is not reflected in the // AST. @@ -1199,8 +1198,8 @@ impl<'a> Resolver<'a> { make_glob_map: make_glob_map == MakeGlobMap::Yes, glob_map: NodeMap(), - used_imports: HashSet::new(), - used_crates: HashSet::new(), + used_imports: FnvHashSet(), + used_crates: FnvHashSet(), maybe_unused_trait_imports: NodeSet(), privacy_errors: Vec::new(), @@ -1729,7 +1728,7 @@ impl<'a> Resolver<'a> { match type_parameters { HasTypeParameters(generics, rib_kind) => { let mut function_type_rib = Rib::new(rib_kind); - let mut seen_bindings = HashMap::new(); + let mut seen_bindings = FnvHashMap(); for type_parameter in &generics.ty_params { let name = type_parameter.ident.name; debug!("with_type_parameter_rib: {}", type_parameter.id); @@ -1793,7 +1792,7 @@ impl<'a> Resolver<'a> { self.label_ribs.push(Rib::new(rib_kind)); // Add each argument to the rib. - let mut bindings_list = HashMap::new(); + let mut bindings_list = FnvHashMap(); for argument in &declaration.inputs { self.resolve_pattern(&argument.pat, PatternSource::FnParam, &mut bindings_list); @@ -1994,7 +1993,7 @@ impl<'a> Resolver<'a> { walk_list!(self, visit_expr, &local.init); // Resolve the pattern. - self.resolve_pattern(&local.pat, PatternSource::Let, &mut HashMap::new()); + self.resolve_pattern(&local.pat, PatternSource::Let, &mut FnvHashMap()); } // build a map from pattern identifiers to binding-info's. @@ -2002,7 +2001,7 @@ impl<'a> Resolver<'a> { // that expands into an or-pattern where one 'x' was from the // user and one 'x' came from the macro. fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap { - let mut binding_map = HashMap::new(); + let mut binding_map = FnvHashMap(); pat.walk(&mut |pat| { if let PatKind::Ident(binding_mode, ident, ref sub_pat) = pat.node { @@ -2062,7 +2061,7 @@ impl<'a> Resolver<'a> { fn resolve_arm(&mut self, arm: &Arm) { self.value_ribs.push(Rib::new(NormalRibKind)); - let mut bindings_list = HashMap::new(); + let mut bindings_list = FnvHashMap(); for pattern in &arm.pats { self.resolve_pattern(&pattern, PatternSource::Match, &mut bindings_list); } @@ -2202,7 +2201,7 @@ impl<'a> Resolver<'a> { pat_id: NodeId, outer_pat_id: NodeId, pat_src: PatternSource, - bindings: &mut HashMap) + bindings: &mut FnvHashMap) -> PathResolution { // Add the binding to the local ribs, if it // doesn't already exist in the bindings map. (We @@ -2303,7 +2302,7 @@ impl<'a> Resolver<'a> { pat_src: PatternSource, // Maps idents to the node ID for the // outermost pattern that binds them. - bindings: &mut HashMap) { + bindings: &mut FnvHashMap) { // Visit all direct subpatterns of this pattern. let outer_pat_id = pat.id; pat.walk(&mut |pat| { @@ -3016,7 +3015,7 @@ impl<'a> Resolver<'a> { self.visit_expr(subexpression); self.value_ribs.push(Rib::new(NormalRibKind)); - self.resolve_pattern(pattern, PatternSource::IfLet, &mut HashMap::new()); + self.resolve_pattern(pattern, PatternSource::IfLet, &mut FnvHashMap()); self.visit_block(if_block); self.value_ribs.pop(); @@ -3026,7 +3025,7 @@ impl<'a> Resolver<'a> { ExprKind::WhileLet(ref pattern, ref subexpression, ref block, label) => { self.visit_expr(subexpression); self.value_ribs.push(Rib::new(NormalRibKind)); - self.resolve_pattern(pattern, PatternSource::WhileLet, &mut HashMap::new()); + self.resolve_pattern(pattern, PatternSource::WhileLet, &mut FnvHashMap()); self.resolve_labeled_block(label.map(|l| l.node), expr.id, block); @@ -3036,7 +3035,7 @@ impl<'a> Resolver<'a> { ExprKind::ForLoop(ref pattern, ref subexpression, ref block, label) => { self.visit_expr(subexpression); self.value_ribs.push(Rib::new(NormalRibKind)); - self.resolve_pattern(pattern, PatternSource::For, &mut HashMap::new()); + self.resolve_pattern(pattern, PatternSource::For, &mut FnvHashMap()); self.resolve_labeled_block(label.map(|l| l.node), expr.id, block); @@ -3297,7 +3296,7 @@ impl<'a> Resolver<'a> { fn report_privacy_errors(&self) { if self.privacy_errors.len() == 0 { return } - let mut reported_spans = HashSet::new(); + let mut reported_spans = FnvHashSet(); for &PrivacyError(span, name, binding) in &self.privacy_errors { if !reported_spans.insert(span) { continue } if binding.is_extern_crate() { diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 5e431193a2c4c..a183fc0858aa8 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -80,14 +80,13 @@ use type_of; use value::Value; use Disr; use util::sha2::Sha256; -use util::nodemap::{NodeSet, FnvHashSet}; +use util::nodemap::{NodeSet, FnvHashMap, FnvHashSet}; use arena::TypedArena; use libc::c_uint; use std::ffi::{CStr, CString}; use std::borrow::Cow; use std::cell::{Cell, RefCell}; -use std::collections::HashMap; use std::ptr; use std::rc::Rc; use std::str; @@ -1915,7 +1914,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a } if scx.sess().opts.debugging_opts.print_trans_items.is_some() { - let mut item_to_cgus = HashMap::new(); + let mut item_to_cgus = FnvHashMap(); for cgu in &codegen_units { for (&trans_item, &linkage) in cgu.items() { diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index ad48827a1d039..d0b0242544981 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -16,9 +16,9 @@ use rustc::infer::TypeOrigin; use rustc::ty::subst::Substs; use rustc::ty::FnSig; use rustc::ty::{self, Ty}; +use rustc::util::nodemap::FnvHashMap; use {CrateCtxt, require_same_types}; -use std::collections::{HashMap}; use syntax::abi::Abi; use syntax::ast; use syntax::parse::token; @@ -365,7 +365,7 @@ pub fn check_platform_intrinsic_type(ccx: &CrateCtxt, return } - let mut structural_to_nomimal = HashMap::new(); + let mut structural_to_nomimal = FnvHashMap(); let sig = tcx.no_late_bound_regions(i_ty.ty.fn_sig()).unwrap(); if intr.inputs.len() != sig.inputs.len() { @@ -405,7 +405,7 @@ fn match_intrinsic_type_to_type<'tcx, 'a>( ccx: &CrateCtxt<'a, 'tcx>, position: &str, span: Span, - structural_to_nominal: &mut HashMap<&'a intrinsics::Type, ty::Ty<'tcx>>, + structural_to_nominal: &mut FnvHashMap<&'a intrinsics::Type, ty::Ty<'tcx>>, expected: &'a intrinsics::Type, t: ty::Ty<'tcx>) { use intrinsics::Type::*; diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index a64982cd1bf81..29366823fffdc 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -20,10 +20,10 @@ use rustc::ty::subst::{Subst, Substs}; use rustc::traits; use rustc::ty::{self, Ty, ToPolyTraitRef, TraitRef, TypeFoldable}; use rustc::infer::{InferOk, TypeOrigin}; +use rustc::util::nodemap::FnvHashSet; use syntax::ast; use syntax_pos::{Span, DUMMY_SP}; use rustc::hir; -use std::collections::HashSet; use std::mem; use std::ops::Deref; use std::rc::Rc; @@ -40,7 +40,7 @@ struct ProbeContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { opt_simplified_steps: Option>, inherent_candidates: Vec>, extension_candidates: Vec>, - impl_dups: HashSet, + impl_dups: FnvHashSet, import_id: Option, /// Collects near misses when the candidate functions are missing a `self` keyword and is only @@ -255,7 +255,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { item_name: item_name, inherent_candidates: Vec::new(), extension_candidates: Vec::new(), - impl_dups: HashSet::new(), + impl_dups: FnvHashSet(), import_id: None, steps: Rc::new(steps), opt_simplified_steps: opt_simplified_steps, @@ -574,7 +574,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { expr_id: ast::NodeId) -> Result<(), MethodError<'tcx>> { - let mut duplicates = HashSet::new(); + let mut duplicates = FnvHashSet(); let opt_applicable_traits = self.tcx.trait_map.get(&expr_id); if let Some(applicable_traits) = opt_applicable_traits { for trait_candidate in applicable_traits { @@ -591,7 +591,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { } fn assemble_extension_candidates_for_all_traits(&mut self) -> Result<(), MethodError<'tcx>> { - let mut duplicates = HashSet::new(); + let mut duplicates = FnvHashSet(); for trait_info in suggest::all_traits(self.ccx) { if duplicates.insert(trait_info.def_id) { self.assemble_extension_candidates_for_trait(trait_info.def_id)?; diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index e972a5ca7fb38..fb24971c4251d 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -104,10 +104,9 @@ use CrateCtxt; use TypeAndSubsts; use lint; use util::common::{block_query, ErrorReported, indenter, loop_query}; -use util::nodemap::{DefIdMap, FnvHashMap, NodeMap}; +use util::nodemap::{DefIdMap, FnvHashMap, FnvHashSet, NodeMap}; use std::cell::{Cell, Ref, RefCell}; -use std::collections::{HashSet}; use std::mem::replace; use std::ops::Deref; use syntax::abi::Abi; @@ -2045,7 +2044,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { .filter_map(|t| self.default(t).map(|d| (t, d))) .collect(); - let mut unbound_tyvars = HashSet::new(); + let mut unbound_tyvars = FnvHashSet(); debug!("select_all_obligations_and_apply_defaults: defaults={:?}", default_map); @@ -2192,7 +2191,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // table then apply defaults until we find a conflict. That default must be the one // that caused conflict earlier. fn find_conflicting_default(&self, - unbound_vars: &HashSet>, + unbound_vars: &FnvHashSet>, default_map: &FnvHashMap<&Ty<'tcx>, type_variable::Default<'tcx>>, conflict: Ty<'tcx>) -> Option> { diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 38ec7ba686f6f..6b6a688bf1d18 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -16,8 +16,8 @@ use middle::region::{CodeExtent}; use rustc::infer::TypeOrigin; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt}; +use rustc::util::nodemap::FnvHashSet; -use std::collections::HashSet; use syntax::ast; use syntax_pos::Span; use errors::DiagnosticBuilder; @@ -456,7 +456,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { assert_eq!(ty_predicates.parent, None); let variances = self.tcx().item_variances(item_def_id); - let mut constrained_parameters: HashSet<_> = + let mut constrained_parameters: FnvHashSet<_> = variances[ast_generics.lifetimes.len()..] .iter().enumerate() .filter(|&(_, &variance)| variance != ty::Bivariant) @@ -519,7 +519,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { fn reject_shadowing_type_parameters(tcx: TyCtxt, span: Span, generics: &ty::Generics) { let parent = tcx.lookup_generics(generics.parent.unwrap()); - let impl_params: HashSet<_> = parent.types.iter().map(|tp| tp.name).collect(); + let impl_params: FnvHashSet<_> = parent.types.iter().map(|tp| tp.name).collect(); for method_param in &generics.types { if impl_params.contains(&method_param.name) { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 0074d3930e29f..30b9d15587069 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -73,13 +73,12 @@ use rustc::ty::util::IntTypeExt; use rscope::*; use rustc::dep_graph::DepNode; use util::common::{ErrorReported, MemoizationMap}; -use util::nodemap::{NodeMap, FnvHashMap}; +use util::nodemap::{NodeMap, FnvHashMap, FnvHashSet}; use {CrateCtxt, write_ty_to_tcx}; use rustc_const_math::ConstInt; use std::cell::RefCell; -use std::collections::HashSet; use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::rc::Rc; @@ -1927,9 +1926,9 @@ fn compute_object_lifetime_default<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, { let inline_bounds = from_bounds(ccx, param_bounds); let where_bounds = from_predicates(ccx, param_id, &where_clause.predicates); - let all_bounds: HashSet<_> = inline_bounds.into_iter() - .chain(where_bounds) - .collect(); + let all_bounds: FnvHashSet<_> = inline_bounds.into_iter() + .chain(where_bounds) + .collect(); return if all_bounds.len() > 1 { ty::ObjectLifetimeDefault::Ambiguous } else if all_bounds.len() == 0 { @@ -2146,7 +2145,7 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // The trait reference is an input, so find all type parameters // reachable from there, to start (if this is an inherent impl, // then just examine the self type). - let mut input_parameters: HashSet<_> = + let mut input_parameters: FnvHashSet<_> = ctp::parameters_for(&impl_scheme.ty, false).into_iter().collect(); if let Some(ref trait_ref) = impl_trait_ref { input_parameters.extend(ctp::parameters_for(trait_ref, false)); @@ -2175,7 +2174,7 @@ fn enforce_impl_lifetimes_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let impl_predicates = ccx.tcx.lookup_predicates(impl_def_id); let impl_trait_ref = ccx.tcx.impl_trait_ref(impl_def_id); - let mut input_parameters: HashSet<_> = + let mut input_parameters: FnvHashSet<_> = ctp::parameters_for(&impl_scheme.ty, false).into_iter().collect(); if let Some(ref trait_ref) = impl_trait_ref { input_parameters.extend(ctp::parameters_for(trait_ref, false)); @@ -2183,7 +2182,7 @@ fn enforce_impl_lifetimes_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ctp::identify_constrained_type_params( &impl_predicates.predicates.as_slice(), impl_trait_ref, &mut input_parameters); - let lifetimes_in_associated_types: HashSet<_> = impl_items.iter() + let lifetimes_in_associated_types: FnvHashSet<_> = impl_items.iter() .map(|item| ccx.tcx.impl_or_trait_item(ccx.tcx.map.local_def_id(item.id))) .filter_map(|item| match item { ty::TypeTraitItem(ref assoc_ty) => assoc_ty.ty, diff --git a/src/librustc_typeck/constrained_type_params.rs b/src/librustc_typeck/constrained_type_params.rs index 637df52e3cb03..9e5c3a5d575bf 100644 --- a/src/librustc_typeck/constrained_type_params.rs +++ b/src/librustc_typeck/constrained_type_params.rs @@ -10,7 +10,7 @@ use rustc::ty::{self, Ty}; use rustc::ty::fold::{TypeFoldable, TypeVisitor}; -use std::collections::HashSet; +use rustc::util::nodemap::FnvHashSet; #[derive(Clone, PartialEq, Eq, Hash, Debug)] pub enum Parameter { @@ -71,7 +71,7 @@ impl<'tcx> TypeVisitor<'tcx> for ParameterCollector { pub fn identify_constrained_type_params<'tcx>(predicates: &[ty::Predicate<'tcx>], impl_trait_ref: Option>, - input_parameters: &mut HashSet) + input_parameters: &mut FnvHashSet) { let mut predicates = predicates.to_owned(); setup_constraining_predicates(&mut predicates, impl_trait_ref, input_parameters); @@ -120,7 +120,7 @@ pub fn identify_constrained_type_params<'tcx>(predicates: &[ty::Predicate<'tcx>] /// think of any. pub fn setup_constraining_predicates<'tcx>(predicates: &mut [ty::Predicate<'tcx>], impl_trait_ref: Option>, - input_parameters: &mut HashSet) + input_parameters: &mut FnvHashSet) { // The canonical way of doing the needed topological sort // would be a DFS, but getting the graph and its ownership From 5adf003b990c7fc76cca3a909c6f81cfe4a1102f Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Wed, 24 Aug 2016 10:55:03 +0200 Subject: [PATCH 2/6] Use deterministic `FnvHash{Map,Set}` in rustdoc --- src/librustdoc/clean/inline.rs | 6 ++-- src/librustdoc/clean/mod.rs | 18 +++++------ src/librustdoc/core.rs | 12 +++---- src/librustdoc/html/render.rs | 57 +++++++++++++++++----------------- src/librustdoc/test.rs | 6 ++-- src/librustdoc/visit_ast.rs | 6 ++-- 6 files changed, 53 insertions(+), 52 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 013433336a1d5..20d4c41765540 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -10,7 +10,6 @@ //! Support for inlining external documentation into the current AST. -use std::collections::HashSet; use std::iter::once; use syntax::ast; @@ -21,6 +20,7 @@ use rustc::hir::def::Def; use rustc::hir::def_id::DefId; use rustc::hir::print as pprust; use rustc::ty::{self, TyCtxt}; +use rustc::util::nodemap::FnvHashSet; use rustc_const_eval::lookup_const_by_id; @@ -425,7 +425,7 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext, .into_iter() .map(|meth| meth.name.to_string()) .collect() - }).unwrap_or(HashSet::new()); + }).unwrap_or(FnvHashSet()); ret.push(clean::Item { inner: clean::ImplItem(clean::Impl { @@ -461,7 +461,7 @@ fn build_module<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>, // If we're reexporting a reexport it may actually reexport something in // two namespaces, so the target may be listed twice. Make sure we only // visit each node at most once. - let mut visited = HashSet::new(); + let mut visited = FnvHashSet(); for item in tcx.sess.cstore.item_children(did) { match item.def { cstore::DlDef(Def::ForeignMod(did)) => { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index c8620254b6f42..cd425b7c9ebbd 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -43,10 +43,10 @@ use rustc::hir::print as pprust; use rustc::ty::subst::Substs; use rustc::ty; use rustc::middle::stability; +use rustc::util::nodemap::{FnvHashMap, FnvHashSet}; use rustc::hir; -use std::collections::{HashMap, HashSet}; use std::path::PathBuf; use std::rc::Rc; use std::sync::Arc; @@ -121,7 +121,7 @@ pub struct Crate { pub access_levels: Arc>, // These are later on moved into `CACHEKEY`, leaving the map empty. // Only here so that they can be filtered through the rustdoc passes. - pub external_traits: HashMap, + pub external_traits: FnvHashMap, } struct CrateNum(ast::CrateNum); @@ -1010,7 +1010,7 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics<'tcx>, // Note that associated types also have a sized bound by default, but we // don't actually know the set of associated types right here so that's // handled in cleaning associated types - let mut sized_params = HashSet::new(); + let mut sized_params = FnvHashSet(); where_predicates.retain(|pred| { match *pred { WP::BoundPredicate { ty: Generic(ref g), ref bounds } => { @@ -1656,9 +1656,9 @@ impl From for PrimitiveType { struct SubstAlias<'a, 'tcx: 'a> { tcx: &'a ty::TyCtxt<'a, 'tcx, 'tcx>, // Table type parameter definition -> substituted type - ty_substs: HashMap, + ty_substs: FnvHashMap, // Table node id of lifetime parameter definition -> substituted lifetime - lt_substs: HashMap, + lt_substs: FnvHashMap, } impl<'a, 'tcx: 'a, 'b: 'tcx> Folder for SubstAlias<'a, 'tcx> { @@ -1727,8 +1727,8 @@ impl Clean for hir::Ty { let item = tcx.map.expect_item(node_id); if let hir::ItemTy(ref ty, ref generics) = item.node { let provided_params = &path.segments.last().unwrap().parameters; - let mut ty_substs = HashMap::new(); - let mut lt_substs = HashMap::new(); + let mut ty_substs = FnvHashMap(); + let mut lt_substs = FnvHashMap(); for (i, ty_param) in generics.ty_params.iter().enumerate() { let ty_param_def = tcx.expect_def(ty_param.id); if let Some(ty) = provided_params.types().get(i).cloned() @@ -2384,7 +2384,7 @@ impl Clean for hir::ImplPolarity { pub struct Impl { pub unsafety: hir::Unsafety, pub generics: Generics, - pub provided_trait_methods: HashSet, + pub provided_trait_methods: FnvHashSet, pub trait_: Option, pub for_: Type, pub items: Vec, @@ -2410,7 +2410,7 @@ impl Clean> for doctree::Impl { .map(|meth| meth.name.to_string()) .collect() }) - }).unwrap_or(HashSet::new()); + }).unwrap_or(FnvHashSet()); ret.push(Item { name: None, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 8032b5c31046e..26f792a1fdf99 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -18,6 +18,7 @@ use rustc::middle::privacy::AccessLevels; use rustc::ty::{self, TyCtxt}; use rustc::hir::map as hir_map; use rustc::lint; +use rustc::util::nodemap::{FnvHashMap, FnvHashSet}; use rustc_trans::back::link; use rustc_resolve as resolve; use rustc_metadata::cstore::CStore; @@ -28,7 +29,6 @@ use errors; use errors::emitter::ColorConfig; use std::cell::{RefCell, Cell}; -use std::collections::{HashMap, HashSet}; use std::rc::Rc; use visit_ast::RustdocVisitor; @@ -45,13 +45,13 @@ pub enum MaybeTyped<'a, 'tcx: 'a> { NotTyped(&'a session::Session) } -pub type ExternalPaths = HashMap, clean::TypeKind)>; +pub type ExternalPaths = FnvHashMap, clean::TypeKind)>; pub struct DocContext<'a, 'tcx: 'a> { pub map: &'a hir_map::Map<'tcx>, pub maybe_typed: MaybeTyped<'a, 'tcx>, pub input: Input, - pub populated_crate_impls: RefCell>, + pub populated_crate_impls: RefCell>, pub deref_trait_did: Cell>, // Note that external items for which `doc(hidden)` applies to are shown as // non-reachable while local items aren't. This is because we're reusing @@ -61,7 +61,7 @@ pub struct DocContext<'a, 'tcx: 'a> { /// Later on moved into `html::render::CACHE_KEY` pub renderinfo: RefCell, /// Later on moved through `clean::Crate` into `html::render::CACHE_KEY` - pub external_traits: RefCell>, + pub external_traits: RefCell>, } impl<'b, 'tcx> DocContext<'b, 'tcx> { @@ -178,10 +178,10 @@ pub fn run_core(search_paths: SearchPaths, map: &tcx.map, maybe_typed: Typed(tcx), input: input, - populated_crate_impls: RefCell::new(HashSet::new()), + populated_crate_impls: RefCell::new(FnvHashSet()), deref_trait_did: Cell::new(None), access_levels: RefCell::new(access_levels), - external_traits: RefCell::new(HashMap::new()), + external_traits: RefCell::new(FnvHashMap()), renderinfo: RefCell::new(Default::default()), }; debug!("crate: {:?}", ctxt.map.krate()); diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 6993f85c3d9a4..5cb5cc051870b 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -37,7 +37,7 @@ pub use self::ExternalLocation::*; use std::ascii::AsciiExt; use std::cell::RefCell; use std::cmp::Ordering; -use std::collections::{BTreeMap, HashMap, HashSet}; +use std::collections::BTreeMap; use std::default::Default; use std::error; use std::fmt::{self, Display, Formatter}; @@ -61,6 +61,7 @@ use rustc::middle::privacy::AccessLevels; use rustc::middle::stability; use rustc::session::config::get_unstable_features_setting; use rustc::hir; +use rustc::util::nodemap::{FnvHashMap, FnvHashSet}; use clean::{self, Attributes, GetDefId}; use doctree; @@ -114,9 +115,9 @@ pub struct SharedContext { /// `true`. pub include_sources: bool, /// The local file sources we've emitted and their respective url-paths. - pub local_sources: HashMap, + pub local_sources: FnvHashMap, /// All the passes that were run on this crate. - pub passes: HashSet, + pub passes: FnvHashSet, /// The base-URL of the issue tracker for when an item has been tagged with /// an issue number. pub issue_tracker_base_url: Option, @@ -211,7 +212,7 @@ pub struct Cache { /// Mapping of typaram ids to the name of the type parameter. This is used /// when pretty-printing a type (so pretty printing doesn't have to /// painfully maintain a context like this) - pub typarams: HashMap, + pub typarams: FnvHashMap, /// Maps a type id to all known implementations for that type. This is only /// recognized for intra-crate `ResolvedPath` types, and is used to print @@ -219,35 +220,35 @@ pub struct Cache { /// /// The values of the map are a list of implementations and documentation /// found on that implementation. - pub impls: HashMap>, + pub impls: FnvHashMap>, /// Maintains a mapping of local crate node ids to the fully qualified name /// and "short type description" of that node. This is used when generating /// URLs when a type is being linked to. External paths are not located in /// this map because the `External` type itself has all the information /// necessary. - pub paths: HashMap, ItemType)>, + pub paths: FnvHashMap, ItemType)>, /// Similar to `paths`, but only holds external paths. This is only used for /// generating explicit hyperlinks to other crates. - pub external_paths: HashMap, ItemType)>, + pub external_paths: FnvHashMap, ItemType)>, /// This map contains information about all known traits of this crate. /// Implementations of a crate should inherit the documentation of the /// parent trait if no extra documentation is specified, and default methods /// should show up in documentation about trait implementations. - pub traits: HashMap, + pub traits: FnvHashMap, /// When rendering traits, it's often useful to be able to list all /// implementors of the trait, and this mapping is exactly, that: a mapping /// of trait ids to the list of known implementors of the trait - pub implementors: HashMap>, + pub implementors: FnvHashMap>, /// Cache of where external crate documentation can be found. - pub extern_locations: HashMap, + pub extern_locations: FnvHashMap, /// Cache of where documentation for primitives can be found. - pub primitive_locations: HashMap, + pub primitive_locations: FnvHashMap, // Note that external items for which `doc(hidden)` applies to are shown as // non-reachable while local items aren't. This is because we're reusing @@ -260,7 +261,7 @@ pub struct Cache { parent_stack: Vec, parent_is_trait_impl: bool, search_index: Vec, - seen_modules: HashSet, + seen_modules: FnvHashSet, seen_mod: bool, stripped_mod: bool, deref_trait_did: Option, @@ -277,9 +278,9 @@ pub struct Cache { /// Later on moved into `CACHE_KEY`. #[derive(Default)] pub struct RenderInfo { - pub inlined: HashSet, + pub inlined: FnvHashSet, pub external_paths: ::core::ExternalPaths, - pub external_typarams: HashMap, + pub external_typarams: FnvHashMap, pub deref_trait_did: Option, } @@ -377,10 +378,10 @@ impl ToJson for IndexItemFunctionType { thread_local!(static CACHE_KEY: RefCell> = Default::default()); thread_local!(pub static CURRENT_LOCATION_KEY: RefCell> = RefCell::new(Vec::new())); -thread_local!(static USED_ID_MAP: RefCell> = +thread_local!(static USED_ID_MAP: RefCell> = RefCell::new(init_ids())); -fn init_ids() -> HashMap { +fn init_ids() -> FnvHashMap { [ "main", "search", @@ -407,7 +408,7 @@ pub fn reset_ids(embedded: bool) { *s.borrow_mut() = if embedded { init_ids() } else { - HashMap::new() + FnvHashMap() }; }); } @@ -432,7 +433,7 @@ pub fn derive_id(candidate: String) -> String { pub fn run(mut krate: clean::Crate, external_html: &ExternalHtml, dst: PathBuf, - passes: HashSet, + passes: FnvHashSet, css_file_extension: Option, renderinfo: RenderInfo) -> Result<(), Error> { let src_root = match krate.src.parent() { @@ -443,7 +444,7 @@ pub fn run(mut krate: clean::Crate, src_root: src_root, passes: passes, include_sources: true, - local_sources: HashMap::new(), + local_sources: FnvHashMap(), issue_tracker_base_url: None, layout: layout::Layout { logo: "".to_string(), @@ -513,22 +514,22 @@ pub fn run(mut krate: clean::Crate, .collect(); let mut cache = Cache { - impls: HashMap::new(), + impls: FnvHashMap(), external_paths: external_paths, - paths: HashMap::new(), - implementors: HashMap::new(), + paths: FnvHashMap(), + implementors: FnvHashMap(), stack: Vec::new(), parent_stack: Vec::new(), search_index: Vec::new(), parent_is_trait_impl: false, - extern_locations: HashMap::new(), - primitive_locations: HashMap::new(), - seen_modules: HashSet::new(), + extern_locations: FnvHashMap(), + primitive_locations: FnvHashMap(), + seen_modules: FnvHashSet(), seen_mod: false, stripped_mod: false, access_levels: krate.access_levels.clone(), orphan_methods: Vec::new(), - traits: mem::replace(&mut krate.external_traits, HashMap::new()), + traits: mem::replace(&mut krate.external_traits, FnvHashMap()), deref_trait_did: deref_trait_did, typarams: external_typarams, }; @@ -574,7 +575,7 @@ pub fn run(mut krate: clean::Crate, /// Build the search index from the collected metadata fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { - let mut nodeid_to_pathid = HashMap::new(); + let mut nodeid_to_pathid = FnvHashMap(); let mut crate_items = Vec::with_capacity(cache.search_index.len()); let mut crate_paths = Vec::::new(); @@ -2515,7 +2516,7 @@ fn render_struct(w: &mut fmt::Formatter, it: &clean::Item, #[derive(Copy, Clone)] enum AssocItemLink<'a> { Anchor(Option<&'a str>), - GotoSource(DefId, &'a HashSet), + GotoSource(DefId, &'a FnvHashSet), } impl<'a> AssocItemLink<'a> { diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 7d1dbbe5dc07d..e7edf8d1cabe2 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -9,7 +9,6 @@ // except according to those terms. use std::cell::{RefCell, Cell}; -use std::collections::{HashMap, HashSet}; use std::env; use std::ffi::OsString; use std::io::prelude::*; @@ -29,6 +28,7 @@ use rustc::session::{self, config}; use rustc::session::config::{get_unstable_features_setting, OutputType, OutputTypes, Externs}; use rustc::session::search_paths::{SearchPaths, PathKind}; +use rustc::util::nodemap::{FnvHashMap, FnvHashSet}; use rustc_back::dynamic_lib::DynamicLibrary; use rustc_back::tempdir::TempDir; use rustc_driver::{driver, Compilation}; @@ -107,8 +107,8 @@ pub fn run(input: &str, map: &map, maybe_typed: core::NotTyped(&sess), input: input, - external_traits: RefCell::new(HashMap::new()), - populated_crate_impls: RefCell::new(HashSet::new()), + external_traits: RefCell::new(FnvHashMap()), + populated_crate_impls: RefCell::new(FnvHashSet()), deref_trait_did: Cell::new(None), access_levels: Default::default(), renderinfo: Default::default(), diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 0334c5ef5c4f4..f6084180f0bd1 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -11,7 +11,6 @@ //! Rust AST Visitor. Extracts useful information and massages it into a form //! usable for clean -use std::collections::HashSet; use std::mem; use syntax::abi; @@ -23,6 +22,7 @@ use syntax_pos::Span; use rustc::hir::map as hir_map; use rustc::hir::def::Def; use rustc::middle::privacy::AccessLevel; +use rustc::util::nodemap::FnvHashSet; use rustc::hir; @@ -42,14 +42,14 @@ pub struct RustdocVisitor<'a, 'tcx: 'a> { pub module: Module, pub attrs: hir::HirVec, pub cx: &'a core::DocContext<'a, 'tcx>, - view_item_stack: HashSet, + view_item_stack: FnvHashSet, inlining_from_glob: bool, } impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { pub fn new(cx: &'a core::DocContext<'a, 'tcx>) -> RustdocVisitor<'a, 'tcx> { // If the root is reexported, terminate all recursion. - let mut stack = HashSet::new(); + let mut stack = FnvHashSet(); stack.insert(ast::CRATE_NODE_ID); RustdocVisitor { module: Module::new(None), From 2eeca3ccd254b49aef83f12a1cb4179a686e8551 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Tue, 23 Aug 2016 22:02:47 +0200 Subject: [PATCH 3/6] Make metadata encoding deterministic `ty::Predicate` was being used as a key for a hash map, but its hash implementation indirectly hashed addresses, which vary between each compiler run. This is fixed by sorting predicates by their ID before encoding them. In my tests, rustc is now able to produce deterministic results when compiling libcore and libstd. I've beefed up `run-make/reproducible-build` to compare the produced artifacts bit-by-bit. This doesn't catch everything, but should be a good start. cc #34902 --- src/librustc_metadata/encoder.rs | 7 +++++- src/test/run-make/reproducible-build/Makefile | 22 +++++++++++-------- .../reproducible-build-aux.rs | 8 ++++++- .../reproducible-build/reproducible-build.rs | 8 +++---- 4 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 9a668b69b2eeb..f99bdf3b890cb 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -862,8 +862,13 @@ fn encode_xrefs<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>, xrefs: FnvHashMap, u32>) { let mut xref_positions = vec![0; xrefs.len()]; + + // Encode XRefs sorted by their ID + let mut sorted_xrefs: Vec<_> = xrefs.into_iter().collect(); + sorted_xrefs.sort_by_key(|&(_, id)| id); + rbml_w.start_tag(tag_xref_data); - for (xref, id) in xrefs.into_iter() { + for (xref, id) in sorted_xrefs.into_iter() { xref_positions[id as usize] = rbml_w.mark_stable_position() as u32; match xref { XRef::Predicate(p) => { diff --git a/src/test/run-make/reproducible-build/Makefile b/src/test/run-make/reproducible-build/Makefile index 8e799ca1a4303..8b22dd021a9e7 100644 --- a/src/test/run-make/reproducible-build/Makefile +++ b/src/test/run-make/reproducible-build/Makefile @@ -1,20 +1,24 @@ -include ../tools.mk all: $(RUSTC) reproducible-build-aux.rs + mv libreproducible_build_aux.rlib first.rlib + $(RUSTC) reproducible-build-aux.rs + cp libreproducible_build_aux.rlib second.rlib + cmp "first.rlib" "second.rlib" || exit 1 $(RUSTC) reproducible-build.rs -o"$(TMPDIR)/reproducible-build1" $(RUSTC) reproducible-build.rs -o"$(TMPDIR)/reproducible-build2" - nm "$(TMPDIR)/reproducible-build1" | sort > "$(TMPDIR)/reproducible-build1.nm" - nm "$(TMPDIR)/reproducible-build2" | sort > "$(TMPDIR)/reproducible-build2.nm" - cmp "$(TMPDIR)/reproducible-build1.nm" "$(TMPDIR)/reproducible-build2.nm" || exit 1 + cmp "$(TMPDIR)/reproducible-build1" "$(TMPDIR)/reproducible-build2" || exit 1 + $(RUSTC) reproducible-build-aux.rs -g + mv libreproducible_build_aux.rlib first.rlib $(RUSTC) reproducible-build-aux.rs -g + cp libreproducible_build_aux.rlib second.rlib $(RUSTC) reproducible-build.rs -g -o"$(TMPDIR)/reproducible-build1-debug" $(RUSTC) reproducible-build.rs -g -o"$(TMPDIR)/reproducible-build2-debug" - nm "$(TMPDIR)/reproducible-build1-debug" | sort > "$(TMPDIR)/reproducible-build1-debug.nm" - nm "$(TMPDIR)/reproducible-build2-debug" | sort > "$(TMPDIR)/reproducible-build2-debug.nm" - cmp "$(TMPDIR)/reproducible-build1-debug.nm" "$(TMPDIR)/reproducible-build2-debug.nm" || exit 1 + cmp "$(TMPDIR)/reproducible-build1-debug" "$(TMPDIR)/reproducible-build2-debug" || exit 1 + $(RUSTC) reproducible-build-aux.rs -O + mv libreproducible_build_aux.rlib first.rlib $(RUSTC) reproducible-build-aux.rs -O + cp libreproducible_build_aux.rlib second.rlib $(RUSTC) reproducible-build.rs -O -o"$(TMPDIR)/reproducible-build1-opt" $(RUSTC) reproducible-build.rs -O -o"$(TMPDIR)/reproducible-build2-opt" - nm "$(TMPDIR)/reproducible-build1-opt" | sort > "$(TMPDIR)/reproducible-build1-opt.nm" - nm "$(TMPDIR)/reproducible-build2-opt" | sort > "$(TMPDIR)/reproducible-build2-opt.nm" - cmp "$(TMPDIR)/reproducible-build1-opt.nm" "$(TMPDIR)/reproducible-build2-opt.nm" || exit 1 + cmp "$(TMPDIR)/reproducible-build1-opt" "$(TMPDIR)/reproducible-build2-opt" || exit 1 diff --git a/src/test/run-make/reproducible-build/reproducible-build-aux.rs b/src/test/run-make/reproducible-build/reproducible-build-aux.rs index 9ef853e79960b..73a62eee265cd 100644 --- a/src/test/run-make/reproducible-build/reproducible-build-aux.rs +++ b/src/test/run-make/reproducible-build/reproducible-build-aux.rs @@ -33,6 +33,12 @@ pub enum Enum { pub struct TupleStruct(pub i8, pub i16, pub i32, pub i64); -pub trait Trait { +pub trait Marker {} +impl Marker for char {} +impl Marker for (T, U) {} + +pub trait Trait where T1: 'static { + type Assoc: Marker; + fn foo(&self); } diff --git a/src/test/run-make/reproducible-build/reproducible-build.rs b/src/test/run-make/reproducible-build/reproducible-build.rs index dc7c702e5cc67..a732cc11d6061 100644 --- a/src/test/run-make/reproducible-build/reproducible-build.rs +++ b/src/test/run-make/reproducible-build/reproducible-build.rs @@ -67,7 +67,9 @@ impl Trait for u64 { fn foo(&self) {} } -impl reproducible_build_aux::Trait for TupleStruct { +impl reproducible_build_aux::Trait for TupleStruct { + type Assoc = (u8, i16); + fn foo(&self) {} } @@ -117,12 +119,10 @@ fn main() { let _ = reproducible_build_aux::Enum::Variant3 { x: 0 }; let _ = reproducible_build_aux::TupleStruct(1, 2, 3, 4); - let object_shim: &reproducible_build_aux::Trait = &TupleStruct(0, 1, 2, 3); + let object_shim: &reproducible_build_aux::Trait = &TupleStruct(0, 1, 2, 3); object_shim.foo(); let pointer_shim: &Fn(i32) = ®ular_fn; TupleStruct(1, 2, 3, 4).bar(); } - - From dca01f9443c0337e96fd2d7d72c64ba35a578230 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 25 Aug 2016 17:53:41 +0200 Subject: [PATCH 4/6] fix tidy --- src/test/run-make/reproducible-build/reproducible-build.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/test/run-make/reproducible-build/reproducible-build.rs b/src/test/run-make/reproducible-build/reproducible-build.rs index a732cc11d6061..17c2e87b5c1a6 100644 --- a/src/test/run-make/reproducible-build/reproducible-build.rs +++ b/src/test/run-make/reproducible-build/reproducible-build.rs @@ -67,7 +67,8 @@ impl Trait for u64 { fn foo(&self) {} } -impl reproducible_build_aux::Trait for TupleStruct { +impl +reproducible_build_aux::Trait for TupleStruct { type Assoc = (u8, i16); fn foo(&self) {} @@ -119,7 +120,8 @@ fn main() { let _ = reproducible_build_aux::Enum::Variant3 { x: 0 }; let _ = reproducible_build_aux::TupleStruct(1, 2, 3, 4); - let object_shim: &reproducible_build_aux::Trait = &TupleStruct(0, 1, 2, 3); + let object_shim: &reproducible_build_aux::Trait = + &TupleStruct(0, 1, 2, 3); object_shim.foo(); let pointer_shim: &Fn(i32) = ®ular_fn; From e468ede6247590c3cdef196bcf62c17b55d3fddb Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 25 Aug 2016 21:37:36 +0200 Subject: [PATCH 5/6] Fix the reproducible-build test --- src/test/run-make/reproducible-build/Makefile | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/test/run-make/reproducible-build/Makefile b/src/test/run-make/reproducible-build/Makefile index 8b22dd021a9e7..8db9e0ec078f6 100644 --- a/src/test/run-make/reproducible-build/Makefile +++ b/src/test/run-make/reproducible-build/Makefile @@ -1,24 +1,26 @@ -include ../tools.mk all: $(RUSTC) reproducible-build-aux.rs - mv libreproducible_build_aux.rlib first.rlib + mv "$(TMPDIR)/libreproducible_build_aux.rlib" "$(TMPDIR)/first.rlib" $(RUSTC) reproducible-build-aux.rs - cp libreproducible_build_aux.rlib second.rlib - cmp "first.rlib" "second.rlib" || exit 1 + cp "$(TMPDIR)/libreproducible_build_aux.rlib" "$(TMPDIR)/second.rlib" + cmp "$(TMPDIR)/first.rlib" "$(TMPDIR)/second.rlib" || exit 1 $(RUSTC) reproducible-build.rs -o"$(TMPDIR)/reproducible-build1" $(RUSTC) reproducible-build.rs -o"$(TMPDIR)/reproducible-build2" cmp "$(TMPDIR)/reproducible-build1" "$(TMPDIR)/reproducible-build2" || exit 1 $(RUSTC) reproducible-build-aux.rs -g - mv libreproducible_build_aux.rlib first.rlib + mv "$(TMPDIR)/libreproducible_build_aux.rlib" "$(TMPDIR)/first.rlib" $(RUSTC) reproducible-build-aux.rs -g - cp libreproducible_build_aux.rlib second.rlib + cp "$(TMPDIR)/libreproducible_build_aux.rlib" "$(TMPDIR)/second.rlib" + cmp "$(TMPDIR)/first.rlib" "$(TMPDIR)/second.rlib" || exit 1 $(RUSTC) reproducible-build.rs -g -o"$(TMPDIR)/reproducible-build1-debug" $(RUSTC) reproducible-build.rs -g -o"$(TMPDIR)/reproducible-build2-debug" cmp "$(TMPDIR)/reproducible-build1-debug" "$(TMPDIR)/reproducible-build2-debug" || exit 1 $(RUSTC) reproducible-build-aux.rs -O - mv libreproducible_build_aux.rlib first.rlib + mv "$(TMPDIR)/libreproducible_build_aux.rlib" "$(TMPDIR)/first.rlib" $(RUSTC) reproducible-build-aux.rs -O - cp libreproducible_build_aux.rlib second.rlib + cp "$(TMPDIR)/libreproducible_build_aux.rlib" "$(TMPDIR)/second.rlib" + cmp "$(TMPDIR)/first.rlib" "$(TMPDIR)/second.rlib" || exit 1 $(RUSTC) reproducible-build.rs -O -o"$(TMPDIR)/reproducible-build1-opt" $(RUSTC) reproducible-build.rs -O -o"$(TMPDIR)/reproducible-build2-opt" cmp "$(TMPDIR)/reproducible-build1-opt" "$(TMPDIR)/reproducible-build2-opt" || exit 1 From 8766c18473c23502c37a6edfe999999ed86053c2 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 28 Aug 2016 15:37:37 +0200 Subject: [PATCH 6/6] Revert changes to the reproducible-builds test --- src/test/run-make/reproducible-build/Makefile | 24 +++++++------------ .../reproducible-build-aux.rs | 8 +------ .../reproducible-build/reproducible-build.rs | 10 ++++---- 3 files changed, 14 insertions(+), 28 deletions(-) diff --git a/src/test/run-make/reproducible-build/Makefile b/src/test/run-make/reproducible-build/Makefile index 8db9e0ec078f6..8e799ca1a4303 100644 --- a/src/test/run-make/reproducible-build/Makefile +++ b/src/test/run-make/reproducible-build/Makefile @@ -1,26 +1,20 @@ -include ../tools.mk all: $(RUSTC) reproducible-build-aux.rs - mv "$(TMPDIR)/libreproducible_build_aux.rlib" "$(TMPDIR)/first.rlib" - $(RUSTC) reproducible-build-aux.rs - cp "$(TMPDIR)/libreproducible_build_aux.rlib" "$(TMPDIR)/second.rlib" - cmp "$(TMPDIR)/first.rlib" "$(TMPDIR)/second.rlib" || exit 1 $(RUSTC) reproducible-build.rs -o"$(TMPDIR)/reproducible-build1" $(RUSTC) reproducible-build.rs -o"$(TMPDIR)/reproducible-build2" - cmp "$(TMPDIR)/reproducible-build1" "$(TMPDIR)/reproducible-build2" || exit 1 - $(RUSTC) reproducible-build-aux.rs -g - mv "$(TMPDIR)/libreproducible_build_aux.rlib" "$(TMPDIR)/first.rlib" + nm "$(TMPDIR)/reproducible-build1" | sort > "$(TMPDIR)/reproducible-build1.nm" + nm "$(TMPDIR)/reproducible-build2" | sort > "$(TMPDIR)/reproducible-build2.nm" + cmp "$(TMPDIR)/reproducible-build1.nm" "$(TMPDIR)/reproducible-build2.nm" || exit 1 $(RUSTC) reproducible-build-aux.rs -g - cp "$(TMPDIR)/libreproducible_build_aux.rlib" "$(TMPDIR)/second.rlib" - cmp "$(TMPDIR)/first.rlib" "$(TMPDIR)/second.rlib" || exit 1 $(RUSTC) reproducible-build.rs -g -o"$(TMPDIR)/reproducible-build1-debug" $(RUSTC) reproducible-build.rs -g -o"$(TMPDIR)/reproducible-build2-debug" - cmp "$(TMPDIR)/reproducible-build1-debug" "$(TMPDIR)/reproducible-build2-debug" || exit 1 - $(RUSTC) reproducible-build-aux.rs -O - mv "$(TMPDIR)/libreproducible_build_aux.rlib" "$(TMPDIR)/first.rlib" + nm "$(TMPDIR)/reproducible-build1-debug" | sort > "$(TMPDIR)/reproducible-build1-debug.nm" + nm "$(TMPDIR)/reproducible-build2-debug" | sort > "$(TMPDIR)/reproducible-build2-debug.nm" + cmp "$(TMPDIR)/reproducible-build1-debug.nm" "$(TMPDIR)/reproducible-build2-debug.nm" || exit 1 $(RUSTC) reproducible-build-aux.rs -O - cp "$(TMPDIR)/libreproducible_build_aux.rlib" "$(TMPDIR)/second.rlib" - cmp "$(TMPDIR)/first.rlib" "$(TMPDIR)/second.rlib" || exit 1 $(RUSTC) reproducible-build.rs -O -o"$(TMPDIR)/reproducible-build1-opt" $(RUSTC) reproducible-build.rs -O -o"$(TMPDIR)/reproducible-build2-opt" - cmp "$(TMPDIR)/reproducible-build1-opt" "$(TMPDIR)/reproducible-build2-opt" || exit 1 + nm "$(TMPDIR)/reproducible-build1-opt" | sort > "$(TMPDIR)/reproducible-build1-opt.nm" + nm "$(TMPDIR)/reproducible-build2-opt" | sort > "$(TMPDIR)/reproducible-build2-opt.nm" + cmp "$(TMPDIR)/reproducible-build1-opt.nm" "$(TMPDIR)/reproducible-build2-opt.nm" || exit 1 diff --git a/src/test/run-make/reproducible-build/reproducible-build-aux.rs b/src/test/run-make/reproducible-build/reproducible-build-aux.rs index 73a62eee265cd..9ef853e79960b 100644 --- a/src/test/run-make/reproducible-build/reproducible-build-aux.rs +++ b/src/test/run-make/reproducible-build/reproducible-build-aux.rs @@ -33,12 +33,6 @@ pub enum Enum { pub struct TupleStruct(pub i8, pub i16, pub i32, pub i64); -pub trait Marker {} -impl Marker for char {} -impl Marker for (T, U) {} - -pub trait Trait where T1: 'static { - type Assoc: Marker; - +pub trait Trait { fn foo(&self); } diff --git a/src/test/run-make/reproducible-build/reproducible-build.rs b/src/test/run-make/reproducible-build/reproducible-build.rs index 17c2e87b5c1a6..dc7c702e5cc67 100644 --- a/src/test/run-make/reproducible-build/reproducible-build.rs +++ b/src/test/run-make/reproducible-build/reproducible-build.rs @@ -67,10 +67,7 @@ impl Trait for u64 { fn foo(&self) {} } -impl -reproducible_build_aux::Trait for TupleStruct { - type Assoc = (u8, i16); - +impl reproducible_build_aux::Trait for TupleStruct { fn foo(&self) {} } @@ -120,11 +117,12 @@ fn main() { let _ = reproducible_build_aux::Enum::Variant3 { x: 0 }; let _ = reproducible_build_aux::TupleStruct(1, 2, 3, 4); - let object_shim: &reproducible_build_aux::Trait = - &TupleStruct(0, 1, 2, 3); + let object_shim: &reproducible_build_aux::Trait = &TupleStruct(0, 1, 2, 3); object_shim.foo(); let pointer_shim: &Fn(i32) = ®ular_fn; TupleStruct(1, 2, 3, 4).bar(); } + +