]> git.lizzy.rs Git - rust.git/commitdiff
Factor the `RefCell` out of the `Interner`.
authorJeffrey Seyfried <jeffrey.seyfried@gmail.com>
Mon, 11 Jul 2016 20:00:07 +0000 (20:00 +0000)
committerJeffrey Seyfried <jeffrey.seyfried@gmail.com>
Mon, 11 Jul 2016 22:25:08 +0000 (22:25 +0000)
src/libsyntax/parse/token.rs
src/libsyntax/util/interner.rs

index c3908118284756ba6b0a9a9998cb5a19933a7210..ab7ed223bb31820e23c59b7f2f68f84ce07e1e5b 100644 (file)
@@ -21,6 +21,7 @@
 use tokenstream;
 
 use serialize::{Decodable, Decoder, Encodable, Encoder};
+use std::cell::RefCell;
 use std::fmt;
 use std::ops::Deref;
 use std::rc::Rc;
@@ -477,20 +478,20 @@ fn mk_fresh_ident_interner() -> IdentInterner {
 // if an interner exists in TLS, return it. Otherwise, prepare a
 // fresh one.
 // FIXME(eddyb) #8726 This should probably use a thread-local reference.
-pub fn with_ident_interner<T, F: FnOnce(&IdentInterner) -> T>(f: F) -> T {
-    thread_local!(static KEY: IdentInterner = {
-        mk_fresh_ident_interner()
+pub fn with_ident_interner<T, F: FnOnce(&mut IdentInterner) -> T>(f: F) -> T {
+    thread_local!(static KEY: RefCell<IdentInterner> = {
+        RefCell::new(mk_fresh_ident_interner())
     });
-    KEY.with(f)
+    KEY.with(|interner| f(&mut *interner.borrow_mut()))
 }
 
 /// Reset the ident interner to its initial state.
 pub fn reset_ident_interner() {
-    with_ident_interner(|interner| interner.reset(mk_fresh_ident_interner()));
+    with_ident_interner(|interner| *interner = mk_fresh_ident_interner());
 }
 
 pub fn clear_ident_interner() {
-    with_ident_interner(|interner| interner.clear());
+    with_ident_interner(|interner| *interner = IdentInterner::new());
 }
 
 /// Represents a string stored in the thread-local interner. Because the
index 2dd69c769587119084a85871253e528d31092a2f..6bb409715aa39ce999a502b8fde12b3bde60748c 100644 (file)
@@ -15,7 +15,6 @@
 use ast::Name;
 
 use std::borrow::Borrow;
-use std::cell::RefCell;
 use std::collections::HashMap;
 use std::rc::Rc;
 
@@ -28,85 +27,60 @@ fn borrow(&self) -> &str {
     }
 }
 
+#[derive(Default)]
 pub struct Interner {
-    map: RefCell<HashMap<RcStr, Name>>,
-    vect: RefCell<Vec<Rc<String>> >,
+    names: HashMap<RcStr, Name>,
+    strings: Vec<Rc<String>>,
 }
 
 /// When traits can extend traits, we should extend index<Name,T> to get []
 impl Interner {
     pub fn new() -> Self {
-        Interner {
-            map: RefCell::new(HashMap::new()),
-            vect: RefCell::new(Vec::new()),
-        }
+        Interner::default()
     }
 
     pub fn prefill(init: &[&str]) -> Self {
-        let rv = Interner::new();
-        for &v in init { rv.intern(v); }
-        rv
-    }
-
-    pub fn intern<T: Borrow<str> + Into<String>>(&self, val: T) -> Name {
-        let mut map = self.map.borrow_mut();
-        if let Some(&idx) = map.get(val.borrow()) {
-            return idx;
+        let mut this = Interner::new();
+        for &string in init {
+            this.intern(string);
         }
-
-        let new_idx = Name(self.len() as u32);
-        let val = Rc::new(val.into());
-        map.insert(RcStr(val.clone()), new_idx);
-        self.vect.borrow_mut().push(val);
-        new_idx
+        this
     }
 
-    pub fn gensym(&self, val: &str) -> Name {
-        let new_idx = Name(self.len() as u32);
-        // leave out of .map to avoid colliding
-        self.vect.borrow_mut().push(Rc::new(val.to_owned()));
-        new_idx
-    }
-
-    // I want these gensyms to share name pointers
-    // with existing entries. This would be automatic,
-    // except that the existing gensym creates its
-    // own managed ptr using to_managed. I think that
-    // adding this utility function is the most
-    // lightweight way to get what I want, though not
-    // necessarily the cleanest.
-
-    /// Create a gensym with the same name as an existing
-    /// entry.
-    pub fn gensym_copy(&self, idx : Name) -> Name {
-        let new_idx = Name(self.len() as u32);
-        // leave out of map to avoid colliding
-        let mut vect = self.vect.borrow_mut();
-        let existing = (*vect)[idx.0 as usize].clone();
-        vect.push(existing);
-        new_idx
-    }
+    pub fn intern<T: Borrow<str> + Into<String>>(&mut self, string: T) -> Name {
+        if let Some(&name) = self.names.get(string.borrow()) {
+            return name;
+        }
 
-    pub fn get(&self, idx: Name) -> Rc<String> {
-        (*self.vect.borrow())[idx.0 as usize].clone()
+        let name = Name(self.strings.len() as u32);
+        let string = Rc::new(string.into());
+        self.strings.push(string.clone());
+        self.names.insert(RcStr(string), name);
+        name
     }
 
-    pub fn len(&self) -> usize {
-        self.vect.borrow().len()
+    pub fn gensym(&mut self, string: &str) -> Name {
+        let gensym = Name(self.strings.len() as u32);
+        // leave out of `names` to avoid colliding
+        self.strings.push(Rc::new(string.to_owned()));
+        gensym
     }
 
-    pub fn find(&self, val: &str) -> Option<Name> {
-        self.map.borrow().get(val).cloned()
+    /// Create a gensym with the same name as an existing entry.
+    pub fn gensym_copy(&mut self, name: Name) -> Name {
+        let gensym = Name(self.strings.len() as u32);
+        // leave out of `names` to avoid colliding
+        let string = self.strings[name.0 as usize].clone();
+        self.strings.push(string);
+        gensym
     }
 
-    pub fn clear(&self) {
-        *self.map.borrow_mut() = HashMap::new();
-        *self.vect.borrow_mut() = Vec::new();
+    pub fn get(&self, name: Name) -> Rc<String> {
+        self.strings[name.0 as usize].clone()
     }
 
-    pub fn reset(&self, other: Interner) {
-        *self.map.borrow_mut() = other.map.into_inner();
-        *self.vect.borrow_mut() = other.vect.into_inner();
+    pub fn find(&self, string: &str) -> Option<Name> {
+        self.names.get(string).cloned()
     }
 }
 
@@ -117,7 +91,7 @@ mod tests {
 
     #[test]
     fn interner_tests() {
-        let : Interner = Interner::new();
+        let mut i: Interner = Interner::new();
         // first one is zero:
         assert_eq!(i.intern("dog"), Name(0));
         // re-use gets the same entry: