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, syntax_contexts: Vec, markings: HashMap<(SyntaxContext, Mark), SyntaxContext>, - idents: HashMap, + gensym_to_ctxt: HashMap, } 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> PartialEq for Symbol { pub struct Interner { names: HashMap, Symbol>, strings: Vec>, + gensyms: Vec, } impl Interner { @@ -156,15 +165,29 @@ impl Interner { name } - 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 + 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]) + } } - pub fn get(&self, name: Symbol) -> &str { - &self.strings[name.0 as usize] + fn gensym(&mut self, string: &str) -> Symbol { + let symbol = self.intern(string); + self.gensymed(symbol) + } + + 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)); } }