diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index fa01a1ccca59b..328cb8225478b 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -23,6 +23,7 @@ use rustc_data_structures::indexed_vec::{IndexVec}; use rustc_data_structures::stable_hasher::StableHasher; use serialize::{Encodable, Decodable, Encoder, Decoder}; use session::CrateDisambiguator; +use std::borrow::Borrow; use std::fmt::Write; use std::hash::Hash; use syntax::ast; @@ -389,6 +390,13 @@ pub struct DefPathHash(pub Fingerprint); impl_stable_hash_for!(tuple_struct DefPathHash { fingerprint }); +impl Borrow for DefPathHash { + #[inline] + fn borrow(&self) -> &Fingerprint { + &self.0 + } +} + impl Definitions { /// Create new empty definition map. pub fn new() -> Definitions { diff --git a/src/librustc/ich/fingerprint.rs b/src/librustc/ich/fingerprint.rs index 2a3b1ce6a36a5..a6e35d78dcb5a 100644 --- a/src/librustc/ich/fingerprint.rs +++ b/src/librustc/ich/fingerprint.rs @@ -45,6 +45,18 @@ impl Fingerprint { ) } + // Combines two hashes in an order independent way. Make sure this is what + // you want. + #[inline] + pub fn combine_commutative(self, other: Fingerprint) -> Fingerprint { + let a = (self.1 as u128) << 64 | self.0 as u128; + let b = (other.1 as u128) << 64 | other.0 as u128; + + let c = a.wrapping_add(b); + + Fingerprint((c >> 64) as u64, c as u64) + } + pub fn to_hex(&self) -> String { format!("{:x}{:x}", self.0, self.1) } diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 8917051bfd8ae..70905bf9612f2 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -14,7 +14,7 @@ use hir; use hir::map::DefPathHash; use hir::def_id::{DefId, LocalDefId, CrateNum, CRATE_DEF_INDEX}; -use ich::{StableHashingContext, NodeIdHashingMode}; +use ich::{StableHashingContext, NodeIdHashingMode, Fingerprint}; use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey, StableHasher, StableHasherResult}; use std::mem; @@ -767,15 +767,21 @@ impl<'a> HashStable> for hir::Mod { inner_span.hash_stable(hcx, hasher); - let mut item_ids: Vec = item_ids.iter().map(|id| { - let (def_path_hash, local_id) = id.id.to_stable_hash_key(hcx); - debug_assert_eq!(local_id, hir::ItemLocalId(0)); - def_path_hash - }).collect(); - - item_ids.sort_unstable(); - - item_ids.hash_stable(hcx, hasher); + // Combining the DefPathHashes directly is faster than feeding them + // into the hasher. Because we use a commutative combine, we also don't + // have to sort the array. + let item_ids_hash = item_ids + .iter() + .map(|id| { + let (def_path_hash, local_id) = id.id.to_stable_hash_key(hcx); + debug_assert_eq!(local_id, hir::ItemLocalId(0)); + def_path_hash.0 + }).fold(Fingerprint::ZERO, |a, b| { + a.combine_commutative(b) + }); + + item_ids.len().hash_stable(hcx, hasher); + item_ids_hash.hash_stable(hcx, hasher); } }