about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/hir/map/definitions.rs6
-rw-r--r--src/librustc/ich/impls_syntax.rs2
-rw-r--r--src/libsyntax_pos/hygiene.rs19
-rw-r--r--src/libsyntax_pos/symbol.rs42
4 files changed, 50 insertions, 19 deletions
diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs
index 7d9f92e17b9..4a7fe05df8a 100644
--- a/src/librustc/hir/map/definitions.rs
+++ b/src/librustc/hir/map/definitions.rs
@@ -518,7 +518,9 @@ impl Definitions {
         assert_eq!(index.as_array_index(),
                    self.def_index_to_node[address_space.index()].len());
         self.def_index_to_node[address_space.index()].push(node_id);
-        self.expansions.insert(index, expansion);
+        if expansion.is_modern() {
+            self.expansions.insert(index, expansion);
+        }
 
         debug!("create_def_with_parent: def_index_to_node[{:?} <-> {:?}", index, node_id);
         self.node_to_def_index.insert(node_id, index);
@@ -536,7 +538,7 @@ impl Definitions {
     }
 
     pub fn expansion(&self, index: DefIndex) -> Mark {
-        self.expansions[&index]
+        self.expansions.get(&index).cloned().unwrap_or(Mark::root())
     }
 
     pub fn macro_def_scope(&self, mark: Mark) -> DefId {
diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs
index 7138db01339..0bfe04dd25d 100644
--- a/src/librustc/ich/impls_syntax.rs
+++ b/src/librustc/ich/impls_syntax.rs
@@ -130,7 +130,7 @@ impl_stable_hash_for!(enum ::syntax::ast::FloatTy { F32, F64 });
 impl_stable_hash_for!(enum ::syntax::ast::Unsafety { Unsafe, Normal });
 impl_stable_hash_for!(enum ::syntax::ast::Constness { Const, NotConst });
 impl_stable_hash_for!(enum ::syntax::ast::Defaultness { Default, Final });
-impl_stable_hash_for!(struct ::syntax::ast::Lifetime { id, span, name });
+impl_stable_hash_for!(struct ::syntax::ast::Lifetime { id, span, ident });
 impl_stable_hash_for!(enum ::syntax::ast::StrStyle { Cooked, Raw(pounds) });
 impl_stable_hash_for!(enum ::syntax::ast::AttrStyle { Outer, Inner });
 
diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs
index f23398bda6b..f2ccc3f051e 100644
--- a/src/libsyntax_pos/hygiene.rs
+++ b/src/libsyntax_pos/hygiene.rs
@@ -85,6 +85,10 @@ impl Mark {
         })
     }
 
+    pub fn is_modern(self) -> bool {
+        HygieneData::with(|data| data.marks[self.0 as usize].modern)
+    }
+
     pub fn set_modern(self) {
         HygieneData::with(|data| data.marks[self.0 as usize].modern = true)
     }
@@ -106,7 +110,7 @@ struct HygieneData {
     marks: Vec<MarkData>,
     syntax_contexts: Vec<SyntaxContextData>,
     markings: HashMap<(SyntaxContext, Mark), SyntaxContext>,
-    idents: HashMap<Symbol, Ident>,
+    gensym_to_ctxt: HashMap<Symbol, SyntaxContext>,
 }
 
 impl HygieneData {
@@ -115,7 +119,7 @@ impl HygieneData {
             marks: vec![MarkData::default()],
             syntax_contexts: vec![SyntaxContextData::default()],
             markings: HashMap::new(),
-            idents: HashMap::new(),
+            gensym_to_ctxt: HashMap::new(),
         }
     }
 
@@ -354,15 +358,18 @@ impl Decodable for SyntaxContext {
 impl Symbol {
     pub fn from_ident(ident: Ident) -> Symbol {
         HygieneData::with(|data| {
-            let symbol = Symbol::gensym(&ident.name.as_str());
-            data.idents.insert(symbol, ident);
-            symbol
+            let gensym = ident.name.gensymed();
+            data.gensym_to_ctxt.insert(gensym, ident.ctxt);
+            gensym
         })
     }
 
     pub fn to_ident(self) -> Ident {
         HygieneData::with(|data| {
-            data.idents.get(&self).cloned().unwrap_or(Ident::with_empty_ctxt(self))
+            match data.gensym_to_ctxt.get(&self) {
+                Some(&ctxt) => Ident { name: self.interned(), ctxt: ctxt },
+                None => Ident::with_empty_ctxt(self),
+            }
         })
     }
 }
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index 070fab57afa..17de8129f99 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -77,11 +77,19 @@ impl Symbol {
         with_interner(|interner| interner.intern(string))
     }
 
+    pub fn interned(self) -> Self {
+        with_interner(|interner| interner.interned(self))
+    }
+
     /// gensym's a new usize, using the current interner.
     pub fn gensym(string: &str) -> Self {
         with_interner(|interner| interner.gensym(string))
     }
 
+    pub fn gensymed(self) -> Self {
+        with_interner(|interner| interner.gensymed(self))
+    }
+
     pub fn as_str(self) -> InternedString {
         with_interner(|interner| unsafe {
             InternedString {
@@ -129,6 +137,7 @@ impl<T: ::std::ops::Deref<Target=str>> PartialEq<T> for Symbol {
 pub struct Interner {
     names: HashMap<Box<str>, Symbol>,
     strings: Vec<Box<str>>,
+    gensyms: Vec<Symbol>,
 }
 
 impl Interner {
@@ -156,15 +165,29 @@ impl Interner {
         name
     }
 
+    pub fn interned(&self, symbol: Symbol) -> Symbol {
+        if (symbol.0 as usize) < self.strings.len() {
+            symbol
+        } else {
+            self.interned(self.gensyms[(!0 - symbol.0) as usize])
+        }
+    }
+
     fn gensym(&mut self, string: &str) -> Symbol {
-        let gensym = Symbol(self.strings.len() as u32);
-        // leave out of `names` to avoid colliding
-        self.strings.push(string.to_string().into_boxed_str());
-        gensym
+        let symbol = self.intern(string);
+        self.gensymed(symbol)
     }
 
-    pub fn get(&self, name: Symbol) -> &str {
-        &self.strings[name.0 as usize]
+    fn gensymed(&mut self, symbol: Symbol) -> Symbol {
+        self.gensyms.push(symbol);
+        Symbol(!0 - self.gensyms.len() as u32 + 1)
+    }
+
+    pub fn get(&self, symbol: Symbol) -> &str {
+        match self.strings.get(symbol.0 as usize) {
+            Some(ref string) => string,
+            None => self.get(self.gensyms[(!0 - symbol.0) as usize]),
+        }
     }
 }
 
@@ -379,11 +402,10 @@ mod tests {
         assert_eq!(i.intern("cat"), Symbol(1));
         // dog is still at zero
         assert_eq!(i.intern("dog"), Symbol(0));
-        // gensym gets 3
-        assert_eq!(i.gensym("zebra"), Symbol(2));
+        assert_eq!(i.gensym("zebra"), Symbol(4294967295));
         // gensym of same string gets new number :
-        assert_eq!(i.gensym("zebra"), Symbol(3));
+        assert_eq!(i.gensym("zebra"), Symbol(4294967294));
         // gensym of *existing* string gets new number:
-        assert_eq!(i.gensym("dog"), Symbol(4));
+        assert_eq!(i.gensym("dog"), Symbol(4294967293));
     }
 }