]> git.lizzy.rs Git - rust.git/blobdiff - src/libsyntax/symbol.rs
Fix the fallout
[rust.git] / src / libsyntax / symbol.rs
index 4095845f8d94943c726550fe8b0101a261433dbd..c278171aa109a81120433777fafd9a4504dedb53 100644 (file)
 use std::cell::RefCell;
 use std::collections::HashMap;
 use std::fmt;
-use std::rc::Rc;
 
 /// A symbol is an interned or gensymed string.
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub struct Symbol(u32);
 
+// The interner in thread-local, so `Symbol` shouldn't move between threads.
+impl !Send for Symbol { }
+
 impl Symbol {
     /// Maps a string to its interned representation.
     pub fn intern(string: &str) -> Self {
@@ -34,7 +36,11 @@ pub fn gensym(string: &str) -> Self {
     }
 
     pub fn as_str(self) -> InternedString {
-        with_interner(|interner| InternedString { string: interner.get(self) })
+        with_interner(|interner| unsafe {
+            InternedString {
+                string: ::std::mem::transmute::<&str, &str>(interner.get(self))
+            }
+        })
     }
 
     pub fn as_u32(self) -> u32 {
@@ -74,8 +80,8 @@ fn eq(&self, other: &&str) -> bool {
 
 #[derive(Default)]
 pub struct Interner {
-    names: HashMap<Rc<str>, Symbol>,
-    strings: Vec<Rc<str>>,
+    names: HashMap<Box<str>, Symbol>,
+    strings: Vec<Box<str>>,
 }
 
 impl Interner {
@@ -97,7 +103,7 @@ pub fn intern(&mut self, string: &str) -> Symbol {
         }
 
         let name = Symbol(self.strings.len() as u32);
-        let string = Rc::__from_str(string);
+        let string = string.to_string().into_boxed_str();
         self.strings.push(string.clone());
         self.names.insert(string, name);
         name
@@ -106,12 +112,12 @@ pub fn intern(&mut self, string: &str) -> Symbol {
     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(Rc::__from_str(string));
+        self.strings.push(string.to_string().into_boxed_str());
         gensym
     }
 
-    pub fn get(&self, name: Symbol) -> Rc<str> {
-        self.strings[name.0 as usize].clone()
+    pub fn get(&self, name: Symbol) -> &str {
+        &self.strings[name.0 as usize]
     }
 }
 
@@ -134,7 +140,7 @@ impl Keyword {
         $(
             #[allow(non_upper_case_globals)]
             pub const $konst: Keyword = Keyword {
-                ident: ast::Ident::with_empty_ctxt(ast::Name($index))
+                ident: ast::Ident::with_empty_ctxt(super::Symbol($index))
             };
         )*
     }
@@ -215,6 +221,9 @@ fn fresh() -> Self {
     (53, Default,        "default")
     (54, StaticLifetime, "'static")
     (55, Union,          "union")
+
+    // A virtual keyword that resolves to the crate root when used in a lexical scope.
+    (56, CrateRoot, "{{root}}")
 }
 
 // If an interner exists in TLS, return it. Otherwise, prepare a fresh one.
@@ -225,11 +234,6 @@ fn with_interner<T, F: FnOnce(&mut Interner) -> T>(f: F) -> T {
     INTERNER.with(|interner| f(&mut *interner.borrow_mut()))
 }
 
-/// Reset the ident interner to its initial state.
-pub fn reset_interner() {
-    with_interner(|interner| *interner = Interner::fresh());
-}
-
 /// Represents a string stored in the thread-local interner. Because the
 /// interner lives for the life of the thread, this can be safely treated as an
 /// immortal string, as long as it never crosses between threads.
@@ -241,55 +245,25 @@ pub fn reset_interner() {
 /// somehow.
 #[derive(Clone, PartialEq, Hash, PartialOrd, Eq, Ord)]
 pub struct InternedString {
-    string: Rc<str>,
+    string: &'static str,
 }
 
-impl InternedString {
-    pub fn new(string: &'static str) -> InternedString {
-        InternedString {
-            string: Rc::__from_str(string),
-        }
-    }
-}
+impl !Send for InternedString { }
 
 impl ::std::ops::Deref for InternedString {
     type Target = str;
-    fn deref(&self) -> &str { &self.string }
+    fn deref(&self) -> &str { self.string }
 }
 
 impl fmt::Debug for InternedString {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Debug::fmt(&self.string, f)
+        fmt::Debug::fmt(self.string, f)
     }
 }
 
 impl fmt::Display for InternedString {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Display::fmt(&self.string, f)
-    }
-}
-
-impl<'a> PartialEq<&'a str> for InternedString {
-    fn eq(&self, other: & &'a str) -> bool {
-        PartialEq::eq(&self.string[..], *other)
-    }
-}
-
-impl<'a> PartialEq<InternedString> for &'a str {
-    fn eq(&self, other: &InternedString) -> bool {
-        PartialEq::eq(*self, &other.string[..])
-    }
-}
-
-impl PartialEq<str> for InternedString {
-    fn eq(&self, other: &str) -> bool {
-        PartialEq::eq(&self.string[..], other)
-    }
-}
-
-impl PartialEq<InternedString> for str {
-    fn eq(&self, other: &InternedString) -> bool {
-        PartialEq::eq(self, &other.string[..])
+        fmt::Display::fmt(self.string, f)
     }
 }
 
@@ -301,32 +275,31 @@ fn decode<D: Decoder>(d: &mut D) -> Result<InternedString, D::Error> {
 
 impl Encodable for InternedString {
     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_str(&self.string)
+        s.emit_str(self.string)
     }
 }
 
 #[cfg(test)]
 mod tests {
     use super::*;
-    use ast::Name;
 
     #[test]
     fn interner_tests() {
         let mut i: Interner = Interner::new();
         // first one is zero:
-        assert_eq!(i.intern("dog"), Name(0));
+        assert_eq!(i.intern("dog"), Symbol(0));
         // re-use gets the same entry:
-        assert_eq!(i.intern ("dog"), Name(0));
+        assert_eq!(i.intern ("dog"), Symbol(0));
         // different string gets a different #:
-        assert_eq!(i.intern("cat"), Name(1));
-        assert_eq!(i.intern("cat"), Name(1));
+        assert_eq!(i.intern("cat"), Symbol(1));
+        assert_eq!(i.intern("cat"), Symbol(1));
         // dog is still at zero
-        assert_eq!(i.intern("dog"), Name(0));
+        assert_eq!(i.intern("dog"), Symbol(0));
         // gensym gets 3
-        assert_eq!(i.gensym("zebra"), Name(2));
+        assert_eq!(i.gensym("zebra"), Symbol(2));
         // gensym of same string gets new number :
-        assert_eq!(i.gensym("zebra"), Name(3));
+        assert_eq!(i.gensym("zebra"), Symbol(3));
         // gensym of *existing* string gets new number:
-        assert_eq!(i.gensym("dog"), Name(4));
+        assert_eq!(i.gensym("dog"), Symbol(4));
     }
 }