diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 78b181aa330..daa331fe052 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -27,7 +27,7 @@ use crate::edition::Edition; use crate::symbol::{kw, sym, Symbol}; use crate::with_session_globals; -use crate::{BytePos, CachingSourceMapView, ExpnIdCache, SourceFile, Span, DUMMY_SP}; +use crate::{BytePos, CachingSourceMapView, HashStableContext, SourceFile, Span, DUMMY_SP}; use crate::def_id::{CrateNum, DefId, DefPathHash, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_data_structures::fingerprint::Fingerprint; @@ -36,6 +36,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{Lock, Lrc}; use rustc_macros::HashStable_Generic; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; +use std::cell::RefCell; use std::fmt; use std::hash::Hash; use std::thread::LocalKey; @@ -1407,3 +1408,60 @@ fn update_disambiguator(expn_id: ExpnId) { }; } } + +impl HashStable for SyntaxContext { + fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + const TAG_EXPANSION: u8 = 0; + const TAG_NO_EXPANSION: u8 = 1; + + if *self == SyntaxContext::root() { + TAG_NO_EXPANSION.hash_stable(ctx, hasher); + } else { + TAG_EXPANSION.hash_stable(ctx, hasher); + let (expn_id, transparency) = self.outer_mark(); + expn_id.hash_stable(ctx, hasher); + transparency.hash_stable(ctx, hasher); + } + } +} + +pub type ExpnIdCache = RefCell>>; + +impl HashStable for ExpnId { + fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { + const TAG_ROOT: u8 = 0; + const TAG_NOT_ROOT: u8 = 1; + + if *self == ExpnId::root() { + TAG_ROOT.hash_stable(ctx, hasher); + return; + } + + // Since the same expansion context is usually referenced many + // times, we cache a stable hash of it and hash that instead of + // recursing every time. + let index = self.as_u32() as usize; + let res = CTX::expn_id_cache().with(|cache| cache.borrow().get(index).copied().flatten()); + + if let Some(res) = res { + res.hash_stable(ctx, hasher); + } else { + let new_len = index + 1; + + let mut sub_hasher = StableHasher::new(); + TAG_NOT_ROOT.hash_stable(ctx, &mut sub_hasher); + self.expn_data().hash_stable(ctx, &mut sub_hasher); + let sub_hash: Fingerprint = sub_hasher.finish(); + + CTX::expn_id_cache().with(|cache| { + let mut cache = cache.borrow_mut(); + if cache.len() < new_len { + cache.resize(new_len, None); + } + let prev = cache[index].replace(sub_hash); + assert_eq!(prev, None, "Cache slot was filled"); + }); + sub_hash.hash_stable(ctx, hasher); + } + } +} diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 84bef4b113c..fa591521dbc 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -36,9 +36,9 @@ use source_map::SourceMap; pub mod edition; use edition::Edition; pub mod hygiene; -pub use hygiene::SyntaxContext; use hygiene::Transparency; pub use hygiene::{DesugaringKind, ExpnData, ExpnId, ExpnKind, ForLoopLoc, MacroKind}; +pub use hygiene::{ExpnIdCache, SyntaxContext}; pub mod def_id; use def_id::{CrateNum, DefId, DefPathHash, LOCAL_CRATE}; pub mod lev_distance; @@ -51,12 +51,10 @@ pub use symbol::{sym, Symbol}; mod analyze_source_file; pub mod fatal_error; -use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{Lock, Lrc}; use std::borrow::Cow; -use std::cell::RefCell; use std::cmp::{self, Ordering}; use std::fmt; use std::hash::Hash; @@ -2036,60 +2034,3 @@ where Hash::hash(&len, hasher); } } - -impl HashStable for SyntaxContext { - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - const TAG_EXPANSION: u8 = 0; - const TAG_NO_EXPANSION: u8 = 1; - - if *self == SyntaxContext::root() { - TAG_NO_EXPANSION.hash_stable(ctx, hasher); - } else { - TAG_EXPANSION.hash_stable(ctx, hasher); - let (expn_id, transparency) = self.outer_mark(); - expn_id.hash_stable(ctx, hasher); - transparency.hash_stable(ctx, hasher); - } - } -} - -pub type ExpnIdCache = RefCell>>; - -impl HashStable for ExpnId { - fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) { - const TAG_ROOT: u8 = 0; - const TAG_NOT_ROOT: u8 = 1; - - if *self == ExpnId::root() { - TAG_ROOT.hash_stable(ctx, hasher); - return; - } - - // Since the same expansion context is usually referenced many - // times, we cache a stable hash of it and hash that instead of - // recursing every time. - let index = self.as_u32() as usize; - let res = CTX::expn_id_cache().with(|cache| cache.borrow().get(index).copied().flatten()); - - if let Some(res) = res { - res.hash_stable(ctx, hasher); - } else { - let new_len = index + 1; - - let mut sub_hasher = StableHasher::new(); - TAG_NOT_ROOT.hash_stable(ctx, &mut sub_hasher); - self.expn_data().hash_stable(ctx, &mut sub_hasher); - let sub_hash: Fingerprint = sub_hasher.finish(); - - CTX::expn_id_cache().with(|cache| { - let mut cache = cache.borrow_mut(); - if cache.len() < new_len { - cache.resize(new_len, None); - } - let prev = cache[index].replace(sub_hash); - assert_eq!(prev, None, "Cache slot was filled"); - }); - sub_hash.hash_stable(ctx, hasher); - } - } -}