about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-08-09 14:29:42 +0000
committerbors <bors@rust-lang.org>2020-08-09 14:29:42 +0000
commit543f03d24118d3af784aa98c507c00e30c796a0e (patch)
treeb333a9f3af9e77a2c20181615c5889828f79d8a9
parent8bc801b05019cd3e0ef19e6c4c028d55baa645d2 (diff)
parent1f63a6a572a0f9afc769a88229d80cc81ff04697 (diff)
downloadrust-543f03d24118d3af784aa98c507c00e30c796a0e.tar.gz
rust-543f03d24118d3af784aa98c507c00e30c796a0e.zip
Auto merge of #75134 - Aaron1011:feature/expn-data-parent-hash, r=petrochenkov
Hash parent ExpnData

cc https://github.com/rust-lang/rust/pull/72121#discussion_r460528326
-rw-r--r--src/librustc_span/hygiene.rs8
-rw-r--r--src/librustc_span/lib.rs64
2 files changed, 39 insertions, 33 deletions
diff --git a/src/librustc_span/hygiene.rs b/src/librustc_span/hygiene.rs
index fe5370b9644..4e21d566071 100644
--- a/src/librustc_span/hygiene.rs
+++ b/src/librustc_span/hygiene.rs
@@ -80,8 +80,6 @@ pub enum Transparency {
     Opaque,
 }
 
-pub(crate) const NUM_TRANSPARENCIES: usize = 3;
-
 impl ExpnId {
     pub fn fresh(expn_data: Option<ExpnData>) -> Self {
         HygieneData::with(|data| data.fresh_expn(expn_data))
@@ -619,6 +617,11 @@ impl SyntaxContext {
     }
 
     #[inline]
+    pub fn outer_mark(self) -> (ExpnId, Transparency) {
+        HygieneData::with(|data| data.outer_mark(self))
+    }
+
+    #[inline]
     pub fn outer_mark_with_data(self) -> (ExpnId, Transparency, ExpnData) {
         HygieneData::with(|data| {
             let (expn_id, transparency) = data.outer_mark(self);
@@ -667,7 +670,6 @@ pub struct ExpnData {
     /// The kind of this expansion - macro or compiler desugaring.
     pub kind: ExpnKind,
     /// The expansion that produced this expansion.
-    #[stable_hasher(ignore)]
     pub parent: ExpnId,
     /// The location of the actual macro invocation or syntax sugar , e.g.
     /// `let x = foo!();` or `if let Some(y) = x {}`
diff --git a/src/librustc_span/lib.rs b/src/librustc_span/lib.rs
index 4c441e1cc71..697d88ad063 100644
--- a/src/librustc_span/lib.rs
+++ b/src/librustc_span/lib.rs
@@ -32,8 +32,8 @@ 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};
-use hygiene::{Transparency, NUM_TRANSPARENCIES};
 pub mod def_id;
 use def_id::{CrateNum, DefId, LOCAL_CRATE};
 mod span_encoding;
@@ -1823,47 +1823,51 @@ impl<CTX: HashStableContext> HashStable<CTX> for SyntaxContext {
             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);
+        }
+    }
+}
 
-            // 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.
-            thread_local! {
-                static CACHE: RefCell<Vec<Option<[Option<u64>; NUM_TRANSPARENCIES]>>> = Default::default();
-            }
+impl<CTX: HashStableContext> HashStable<CTX> for ExpnId {
+    fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
+        // 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.
+        thread_local! {
+            static CACHE: RefCell<Vec<Option<Fingerprint>>> = Default::default();
+        }
 
-            let sub_hash: u64 = CACHE.with(|cache| {
-                let (expn_id, transparency, _) = self.outer_mark_with_data();
-                let index = expn_id.as_u32() as usize;
+        const TAG_ROOT: u8 = 0;
+        const TAG_NOT_ROOT: u8 = 1;
 
-                if let Some(sub_hash_cache) = cache.borrow().get(index).copied().flatten() {
-                    if let Some(sub_hash) = sub_hash_cache[transparency as usize] {
-                        return sub_hash;
-                    }
-                }
+        if *self == ExpnId::root() {
+            TAG_ROOT.hash_stable(ctx, hasher);
+            return;
+        }
 
-                let new_len = index + 1;
+        TAG_NOT_ROOT.hash_stable(ctx, hasher);
+        let index = self.as_u32() as usize;
 
-                let mut hasher = StableHasher::new();
-                expn_id.expn_data().hash_stable(ctx, &mut hasher);
-                transparency.hash_stable(ctx, &mut hasher);
+        let res = 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 sub_hash: Fingerprint = hasher.finish();
-                let sub_hash = sub_hash.to_smaller_hash();
+            let mut sub_hasher = StableHasher::new();
+            self.expn_data().hash_stable(ctx, &mut sub_hasher);
+            let sub_hash: Fingerprint = sub_hasher.finish();
 
+            CACHE.with(|cache| {
                 let mut cache = cache.borrow_mut();
                 if cache.len() < new_len {
                     cache.resize(new_len, None);
                 }
-                if let Some(mut sub_hash_cache) = cache[index] {
-                    sub_hash_cache[transparency as usize] = Some(sub_hash);
-                } else {
-                    let mut sub_hash_cache = [None; NUM_TRANSPARENCIES];
-                    sub_hash_cache[transparency as usize] = Some(sub_hash);
-                    cache[index] = Some(sub_hash_cache);
-                }
-                sub_hash
+                cache[index].replace(sub_hash).expect_none("Cache slot was filled");
             });
-
             sub_hash.hash_stable(ctx, hasher);
         }
     }