Skip to content

Commit 060b5c5

Browse files
committed
Factor the RefCell out of the Interner.
1 parent 752d441 commit 060b5c5

File tree

2 files changed

+41
-66
lines changed

2 files changed

+41
-66
lines changed

src/libsyntax/parse/token.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use util::interner::Interner;
2121
use tokenstream;
2222

2323
use serialize::{Decodable, Decoder, Encodable, Encoder};
24+
use std::cell::RefCell;
2425
use std::fmt;
2526
use std::ops::Deref;
2627
use std::rc::Rc;
@@ -477,20 +478,20 @@ pub type IdentInterner = Interner;
477478
// if an interner exists in TLS, return it. Otherwise, prepare a
478479
// fresh one.
479480
// FIXME(eddyb) #8726 This should probably use a thread-local reference.
480-
pub fn with_ident_interner<T, F: FnOnce(&IdentInterner) -> T>(f: F) -> T {
481-
thread_local!(static KEY: IdentInterner = {
482-
mk_fresh_ident_interner()
481+
pub fn with_ident_interner<T, F: FnOnce(&mut IdentInterner) -> T>(f: F) -> T {
482+
thread_local!(static KEY: RefCell<IdentInterner> = {
483+
RefCell::new(mk_fresh_ident_interner())
483484
});
484-
KEY.with(f)
485+
KEY.with(|interner| f(&mut *interner.borrow_mut()))
485486
}
486487

487488
/// Reset the ident interner to its initial state.
488489
pub fn reset_ident_interner() {
489-
with_ident_interner(|interner| interner.reset(mk_fresh_ident_interner()));
490+
with_ident_interner(|interner| *interner = mk_fresh_ident_interner());
490491
}
491492

492493
pub fn clear_ident_interner() {
493-
with_ident_interner(|interner| interner.clear());
494+
with_ident_interner(|interner| *interner = IdentInterner::new());
494495
}
495496

496497
/// Represents a string stored in the thread-local interner. Because the

src/libsyntax/util/interner.rs

Lines changed: 34 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
use ast::Name;
1616

1717
use std::borrow::Borrow;
18-
use std::cell::RefCell;
1918
use std::collections::HashMap;
2019
use std::rc::Rc;
2120

@@ -28,85 +27,60 @@ impl Borrow<str> for RcStr {
2827
}
2928
}
3029

30+
#[derive(Default)]
3131
pub struct Interner {
32-
map: RefCell<HashMap<RcStr, Name>>,
33-
vect: RefCell<Vec<Rc<String>> >,
32+
names: HashMap<RcStr, Name>,
33+
strings: Vec<Rc<String>>,
3434
}
3535

3636
/// When traits can extend traits, we should extend index<Name,T> to get []
3737
impl Interner {
3838
pub fn new() -> Self {
39-
Interner {
40-
map: RefCell::new(HashMap::new()),
41-
vect: RefCell::new(Vec::new()),
42-
}
39+
Interner::default()
4340
}
4441

4542
pub fn prefill(init: &[&str]) -> Self {
46-
let rv = Interner::new();
47-
for &v in init { rv.intern(v); }
48-
rv
49-
}
50-
51-
pub fn intern<T: Borrow<str> + Into<String>>(&self, val: T) -> Name {
52-
let mut map = self.map.borrow_mut();
53-
if let Some(&idx) = map.get(val.borrow()) {
54-
return idx;
43+
let mut this = Interner::new();
44+
for &string in init {
45+
this.intern(string);
5546
}
56-
57-
let new_idx = Name(self.len() as u32);
58-
let val = Rc::new(val.into());
59-
map.insert(RcStr(val.clone()), new_idx);
60-
self.vect.borrow_mut().push(val);
61-
new_idx
47+
this
6248
}
6349

64-
pub fn gensym(&self, val: &str) -> Name {
65-
let new_idx = Name(self.len() as u32);
66-
// leave out of .map to avoid colliding
67-
self.vect.borrow_mut().push(Rc::new(val.to_owned()));
68-
new_idx
69-
}
70-
71-
// I want these gensyms to share name pointers
72-
// with existing entries. This would be automatic,
73-
// except that the existing gensym creates its
74-
// own managed ptr using to_managed. I think that
75-
// adding this utility function is the most
76-
// lightweight way to get what I want, though not
77-
// necessarily the cleanest.
78-
79-
/// Create a gensym with the same name as an existing
80-
/// entry.
81-
pub fn gensym_copy(&self, idx : Name) -> Name {
82-
let new_idx = Name(self.len() as u32);
83-
// leave out of map to avoid colliding
84-
let mut vect = self.vect.borrow_mut();
85-
let existing = (*vect)[idx.0 as usize].clone();
86-
vect.push(existing);
87-
new_idx
88-
}
50+
pub fn intern<T: Borrow<str> + Into<String>>(&mut self, string: T) -> Name {
51+
if let Some(&name) = self.names.get(string.borrow()) {
52+
return name;
53+
}
8954

90-
pub fn get(&self, idx: Name) -> Rc<String> {
91-
(*self.vect.borrow())[idx.0 as usize].clone()
55+
let name = Name(self.strings.len() as u32);
56+
let string = Rc::new(string.into());
57+
self.strings.push(string.clone());
58+
self.names.insert(RcStr(string), name);
59+
name
9260
}
9361

94-
pub fn len(&self) -> usize {
95-
self.vect.borrow().len()
62+
pub fn gensym(&mut self, string: &str) -> Name {
63+
let gensym = Name(self.strings.len() as u32);
64+
// leave out of `names` to avoid colliding
65+
self.strings.push(Rc::new(string.to_owned()));
66+
gensym
9667
}
9768

98-
pub fn find(&self, val: &str) -> Option<Name> {
99-
self.map.borrow().get(val).cloned()
69+
/// Create a gensym with the same name as an existing entry.
70+
pub fn gensym_copy(&mut self, name: Name) -> Name {
71+
let gensym = Name(self.strings.len() as u32);
72+
// leave out of `names` to avoid colliding
73+
let string = self.strings[name.0 as usize].clone();
74+
self.strings.push(string);
75+
gensym
10076
}
10177

102-
pub fn clear(&self) {
103-
*self.map.borrow_mut() = HashMap::new();
104-
*self.vect.borrow_mut() = Vec::new();
78+
pub fn get(&self, name: Name) -> Rc<String> {
79+
self.strings[name.0 as usize].clone()
10580
}
10681

107-
pub fn reset(&self, other: Interner) {
108-
*self.map.borrow_mut() = other.map.into_inner();
109-
*self.vect.borrow_mut() = other.vect.into_inner();
82+
pub fn find(&self, string: &str) -> Option<Name> {
83+
self.names.get(string).cloned()
11084
}
11185
}
11286

@@ -117,7 +91,7 @@ mod tests {
11791

11892
#[test]
11993
fn interner_tests() {
120-
let i : Interner = Interner::new();
94+
let mut i: Interner = Interner::new();
12195
// first one is zero:
12296
assert_eq!(i.intern("dog"), Name(0));
12397
// re-use gets the same entry:

0 commit comments

Comments
 (0)