| //! This module contains `StableHash` implementations for various data types |
| //! from `rustc_middle::ty` in no particular order. |
| |
| use std::cell::RefCell; |
| use std::ptr; |
| |
| use rustc_data_structures::fingerprint::Fingerprint; |
| use rustc_data_structures::fx::FxHashMap; |
| use rustc_data_structures::stable_hash::{ |
| StableHash, StableHashControls, StableHashCtxt, StableHasher, |
| }; |
| use tracing::trace; |
| |
| use crate::{mir, ty}; |
| |
| impl<'tcx, H, T> StableHash for &'tcx ty::list::RawList<H, T> |
| where |
| T: StableHash, |
| { |
| fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) { |
| // Note: this cache makes an *enormous* performance difference on certain benchmarks. E.g. |
| // without it, compiling `diesel-2.2.10` can be 74% slower, and compiling |
| // `deeply-nested-multi` can be ~4,000x slower(!) |
| thread_local! { |
| static CACHE: RefCell<FxHashMap<(*const (), StableHashControls), Fingerprint>> = |
| RefCell::new(Default::default()); |
| } |
| |
| let hash = CACHE.with(|cache| { |
| let key = (ptr::from_ref(*self).cast::<()>(), hcx.stable_hash_controls()); |
| if let Some(&hash) = cache.borrow().get(&key) { |
| return hash; |
| } |
| |
| let mut hasher = StableHasher::new(); |
| self[..].stable_hash(hcx, &mut hasher); |
| |
| let hash: Fingerprint = hasher.finish(); |
| cache.borrow_mut().insert(key, hash); |
| hash |
| }); |
| |
| hash.stable_hash(hcx, hasher); |
| } |
| } |
| |
| impl<'tcx> StableHash for ty::GenericArg<'tcx> { |
| fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) { |
| self.kind().stable_hash(hcx, hasher); |
| } |
| } |
| |
| // AllocIds get resolved to whatever they point to (to be stable) |
| impl StableHash for mir::interpret::AllocId { |
| fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) { |
| ty::tls::with_opt(|tcx| { |
| trace!("hashing {:?}", *self); |
| let tcx = tcx.expect("can't hash AllocIds during hir lowering"); |
| tcx.try_get_global_alloc(*self).stable_hash(hcx, hasher); |
| }); |
| } |
| } |
| |
| impl StableHash for mir::interpret::CtfeProvenance { |
| fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) { |
| self.into_parts().stable_hash(hcx, hasher); |
| } |
| } |