Skip to main content

rustc_middle/ty/
impls_ty.rs

1//! This module contains `StableHash` implementations for various data types
2//! from `rustc_middle::ty` in no particular order.
3
4use std::cell::RefCell;
5use std::ptr;
6
7use rustc_data_structures::fingerprint::Fingerprint;
8use rustc_data_structures::fx::FxHashMap;
9use rustc_data_structures::stable_hasher::{
10    HashingControls, StableHash, StableHashCtxt, StableHasher, ToStableHashKey,
11};
12use tracing::trace;
13
14use crate::middle::region;
15use crate::{mir, ty};
16
17impl<'tcx, H, T> StableHash for &'tcx ty::list::RawList<H, T>
18where
19    T: StableHash,
20{
21    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
22        // Note: this cache makes an *enormous* performance difference on certain benchmarks. E.g.
23        // without it, compiling `diesel-2.2.10` can be 74% slower, and compiling
24        // `deeply-nested-multi` can be ~4,000x slower(!)
25        const CACHE:
    ::std::thread::LocalKey<RefCell<FxHashMap<(*const (), HashingControls),
    Fingerprint>>> =
    {
        #[inline]
        fn __rust_std_internal_init_fn()
            -> RefCell<FxHashMap<(*const (), HashingControls), Fingerprint>> {
            RefCell::new(Default::default())
        }
        unsafe {
            ::std::thread::LocalKey::new(const {
                        if ::std::mem::needs_drop::<RefCell<FxHashMap<(*const (),
                                    HashingControls), Fingerprint>>>() {
                            |__rust_std_internal_init|
                                {
                                    #[thread_local]
                                    static __RUST_STD_INTERNAL_VAL:
                                        ::std::thread::local_impl::LazyStorage<RefCell<FxHashMap<(*const (),
                                        HashingControls), Fingerprint>>, ()> =
                                        ::std::thread::local_impl::LazyStorage::new();
                                    __RUST_STD_INTERNAL_VAL.get_or_init(__rust_std_internal_init,
                                        __rust_std_internal_init_fn)
                                }
                        } else {
                            |__rust_std_internal_init|
                                {
                                    #[thread_local]
                                    static __RUST_STD_INTERNAL_VAL:
                                        ::std::thread::local_impl::LazyStorage<RefCell<FxHashMap<(*const (),
                                        HashingControls), Fingerprint>>, !> =
                                        ::std::thread::local_impl::LazyStorage::new();
                                    __RUST_STD_INTERNAL_VAL.get_or_init(__rust_std_internal_init,
                                        __rust_std_internal_init_fn)
                                }
                        }
                    })
        }
    };thread_local! {
26            static CACHE: RefCell<FxHashMap<(*const (), HashingControls), Fingerprint>> =
27                RefCell::new(Default::default());
28        }
29
30        let hash = CACHE.with(|cache| {
31            let key = (ptr::from_ref(*self).cast::<()>(), hcx.hashing_controls());
32            if let Some(&hash) = cache.borrow().get(&key) {
33                return hash;
34            }
35
36            let mut hasher = StableHasher::new();
37            self[..].stable_hash(hcx, &mut hasher);
38
39            let hash: Fingerprint = hasher.finish();
40            cache.borrow_mut().insert(key, hash);
41            hash
42        });
43
44        hash.stable_hash(hcx, hasher);
45    }
46}
47
48impl<'tcx, H, T> ToStableHashKey for &'tcx ty::list::RawList<H, T>
49where
50    T: StableHash,
51{
52    type KeyType = Fingerprint;
53
54    #[inline]
55    fn to_stable_hash_key<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx) -> Fingerprint {
56        let mut hasher = StableHasher::new();
57        self.stable_hash(hcx, &mut hasher);
58        hasher.finish()
59    }
60}
61
62impl<'tcx> StableHash for ty::GenericArg<'tcx> {
63    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
64        self.kind().stable_hash(hcx, hasher);
65    }
66}
67
68// AllocIds get resolved to whatever they point to (to be stable)
69impl StableHash for mir::interpret::AllocId {
70    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
71        ty::tls::with_opt(|tcx| {
72            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_middle/src/ty/impls_ty.rs:72",
                        "rustc_middle::ty::impls_ty", ::tracing::Level::TRACE,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_middle/src/ty/impls_ty.rs"),
                        ::tracing_core::__macro_support::Option::Some(72u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_middle::ty::impls_ty"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("hashing {0:?}",
                                                    *self) as &dyn Value))])
            });
    } else { ; }
};trace!("hashing {:?}", *self);
73            let tcx = tcx.expect("can't hash AllocIds during hir lowering");
74            tcx.try_get_global_alloc(*self).stable_hash(hcx, hasher);
75        });
76    }
77}
78
79impl StableHash for mir::interpret::CtfeProvenance {
80    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
81        self.into_parts().stable_hash(hcx, hasher);
82    }
83}
84
85impl ToStableHashKey for region::Scope {
86    type KeyType = region::Scope;
87
88    #[inline]
89    fn to_stable_hash_key<Hcx>(&self, _: &mut Hcx) -> region::Scope {
90        *self
91    }
92}