From 6d5f85996e92a8cbc0112926dded59daa2bf9fdd Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Mon, 11 Jul 2016 09:02:16 +0000 Subject: Remove unused field `interner` from the parser. --- src/libsyntax/parse/parser.rs | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/libsyntax') diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index e4875b7c244..a9e50ed7c5b 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -259,7 +259,6 @@ pub struct Parser<'a> { pub restrictions: Restrictions, pub quote_depth: usize, // not (yet) related to the quasiquoter pub reader: Box, - pub interner: Rc, /// The set of seen errors about obsolete syntax. Used to suppress /// extra detail when the same error is seen twice pub obsolete_set: HashSet, @@ -356,7 +355,6 @@ impl<'a> Parser<'a> { Parser { reader: rdr, - interner: token::get_ident_interner(), sess: sess, cfg: cfg, token: tok0.tok, -- cgit 1.4.1-3-g733a5 From f8a934e971fdef496e69e82ab0e7166363efd3f5 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Mon, 11 Jul 2016 07:55:54 +0000 Subject: Encapsulate `RcStr` in `syntax::util::interner`. --- src/libsyntax/parse/token.rs | 11 +++--- src/libsyntax/util/interner.rs | 76 +++++++++++------------------------------- 2 files changed, 25 insertions(+), 62 deletions(-) (limited to 'src/libsyntax') diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 8376d28164d..6ebd2ca6ec1 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -17,8 +17,7 @@ pub use self::Token::*; use ast::{self, BinOpKind}; use ext::mtwt; use ptr::P; -use util::interner::{RcStr, StrInterner}; -use util::interner; +use util::interner::StrInterner; use tokenstream; use serialize::{Decodable, Decoder, Encodable, Encoder}; @@ -397,7 +396,7 @@ macro_rules! declare_keywords {( } fn mk_fresh_ident_interner() -> IdentInterner { - interner::StrInterner::prefill(&[$($string,)*]) + StrInterner::prefill(&[$($string,)*]) } }} @@ -502,19 +501,19 @@ pub fn reset_ident_interner() { /// somehow. #[derive(Clone, PartialEq, Hash, PartialOrd, Eq, Ord)] pub struct InternedString { - string: RcStr, + string: Rc, } impl InternedString { #[inline] pub fn new(string: &'static str) -> InternedString { InternedString { - string: RcStr::new(string), + string: Rc::new(string.to_owned()), } } #[inline] - fn new_from_rc_str(string: RcStr) -> InternedString { + fn new_from_rc_str(string: Rc) -> InternedString { InternedString { string: string, } diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs index 7295b36af0f..68dbd6272f4 100644 --- a/src/libsyntax/util/interner.rs +++ b/src/libsyntax/util/interner.rs @@ -16,11 +16,8 @@ use ast::Name; use std::borrow::Borrow; use std::cell::RefCell; -use std::cmp::Ordering; use std::collections::HashMap; -use std::fmt; use std::hash::Hash; -use std::ops::Deref; use std::rc::Rc; pub struct Interner { @@ -91,56 +88,26 @@ impl Interner { } } -#[derive(Clone, PartialEq, Hash, PartialOrd)] -pub struct RcStr { - string: Rc, -} +#[derive(Clone, PartialEq, Eq, Hash, Debug)] +struct RcStr(Rc); impl RcStr { - pub fn new(string: &str) -> RcStr { - RcStr { - string: Rc::new(string.to_string()), - } - } -} - -impl Eq for RcStr {} - -impl Ord for RcStr { - fn cmp(&self, other: &RcStr) -> Ordering { - self[..].cmp(&other[..]) - } -} - -impl fmt::Debug for RcStr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self[..].fmt(f) - } -} - -impl fmt::Display for RcStr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self[..].fmt(f) + fn new(string: &str) -> Self { + RcStr(Rc::new(string.to_owned())) } } impl Borrow for RcStr { fn borrow(&self) -> &str { - &self.string[..] + &self.0 } } -impl Deref for RcStr { - type Target = str; - - fn deref(&self) -> &str { &self.string[..] } -} - /// A StrInterner differs from Interner in that it accepts /// &str rather than RcStr, resulting in less allocation. pub struct StrInterner { map: RefCell>, - vect: RefCell >, + vect: RefCell> >, } /// When traits can extend traits, we should extend index to get [] @@ -165,8 +132,8 @@ impl StrInterner { } let new_idx = Name(self.len() as u32); - let val = RcStr::new(val); - map.insert(val.clone(), new_idx); + let val = Rc::new(val.to_owned()); + map.insert(RcStr(val.clone()), new_idx); self.vect.borrow_mut().push(val); new_idx } @@ -174,7 +141,7 @@ impl StrInterner { 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(RcStr::new(val)); + self.vect.borrow_mut().push(Rc::new(val.to_owned())); new_idx } @@ -197,7 +164,7 @@ impl StrInterner { new_idx } - pub fn get(&self, idx: Name) -> RcStr { + pub fn get(&self, idx: Name) -> Rc { (*self.vect.borrow())[idx.0 as usize].clone() } @@ -205,12 +172,8 @@ impl StrInterner { self.vect.borrow().len() } - pub fn find(&self, val: &Q) -> Option - where RcStr: Borrow, Q: Eq + Hash { - match (*self.map.borrow()).get(val) { - Some(v) => Some(*v), - None => None, - } + pub fn find(&self, val: &str) -> Option { + self.map.borrow().get(val).cloned() } pub fn clear(&self) { @@ -227,6 +190,7 @@ impl StrInterner { #[cfg(test)] mod tests { use super::*; + use super::RcStr; use ast::Name; #[test] @@ -294,13 +258,13 @@ mod tests { assert_eq!(i.gensym("dog"), Name(4)); // gensym tests again with gensym_copy: assert_eq!(i.gensym_copy(Name(2)), Name(5)); - assert_eq!(i.get(Name(5)), RcStr::new("zebra")); + assert_eq!(*i.get(Name(5)), "zebra"); assert_eq!(i.gensym_copy(Name(2)), Name(6)); - assert_eq!(i.get(Name(6)), RcStr::new("zebra")); - assert_eq!(i.get(Name(0)), RcStr::new("dog")); - assert_eq!(i.get(Name(1)), RcStr::new("cat")); - assert_eq!(i.get(Name(2)), RcStr::new("zebra")); - assert_eq!(i.get(Name(3)), RcStr::new("zebra")); - assert_eq!(i.get(Name(4)), RcStr::new("dog")); + assert_eq!(*i.get(Name(6)), "zebra"); + assert_eq!(*i.get(Name(0)), "dog"); + assert_eq!(*i.get(Name(1)), "cat"); + assert_eq!(*i.get(Name(2)), "zebra"); + assert_eq!(*i.get(Name(3)), "zebra"); + assert_eq!(*i.get(Name(4)), "dog"); } } -- cgit 1.4.1-3-g733a5 From 1eb6d0b485acc5f6e0d9f9b0946000bce12f5bfc Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Mon, 11 Jul 2016 08:00:48 +0000 Subject: Remove `Interner` and rename `StrInterner` to `Interner`. --- src/librustc_metadata/decoder.rs | 4 +- src/librustc_trans/debuginfo/metadata.rs | 6 +- src/libsyntax/parse/token.rs | 6 +- src/libsyntax/util/interner.rs | 149 +++---------------------------- 4 files changed, 21 insertions(+), 144 deletions(-) (limited to 'src/libsyntax') diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 6d3699e9787..6dfd340a3fb 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -450,7 +450,7 @@ pub fn get_adt_def<'a, 'tcx>(intr: &IdentInterner, struct_field_family_to_visibility(ff)) }).chain(reader::tagged_docs(doc, tag_item_unnamed_field).map(|f| { let ff = item_family(f); - let name = intr.intern(&index.to_string()); + let name = intr.intern(index.to_string()); index += 1; ty::FieldDefData::new(item_def_id(f, cdata), name, struct_field_family_to_visibility(ff)) @@ -1187,7 +1187,7 @@ pub fn get_struct_field_names(intr: &IdentInterner, cdata: Cmd, id: DefIndex) reader::tagged_docs(item, tag_item_field).map(|an_item| { item_name(intr, an_item) }).chain(reader::tagged_docs(item, tag_item_unnamed_field).map(|_| { - let name = intr.intern(&index.to_string()); + let name = intr.intern(index.to_string()); index += 1; name })).collect() diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index b84cc028d0c..46813d957dc 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -81,7 +81,7 @@ pub struct UniqueTypeId(ast::Name); // UniqueTypeIds. pub struct TypeMap<'tcx> { // The UniqueTypeIds created so far - unique_id_interner: Interner>, + unique_id_interner: Interner, // A map from UniqueTypeId to debuginfo metadata for that type. This is a 1:1 mapping. unique_id_to_metadata: FnvHashMap, // A map from types to debuginfo metadata. This is a N:1 mapping. @@ -313,7 +313,7 @@ impl<'tcx> TypeMap<'tcx> { // Trim to size before storing permanently unique_type_id.shrink_to_fit(); - let key = self.unique_id_interner.intern(Rc::new(unique_type_id)); + let key = self.unique_id_interner.intern(unique_type_id); self.type_to_unique_id.insert(type_, UniqueTypeId(key)); return UniqueTypeId(key); @@ -383,7 +383,7 @@ impl<'tcx> TypeMap<'tcx> { let enum_variant_type_id = format!("{}::{}", &self.get_unique_type_id_as_string(enum_type_id), variant_name); - let interner_key = self.unique_id_interner.intern(Rc::new(enum_variant_type_id)); + let interner_key = self.unique_id_interner.intern(enum_variant_type_id); UniqueTypeId(interner_key) } } diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 6ebd2ca6ec1..222cf65b78e 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -17,7 +17,7 @@ pub use self::Token::*; use ast::{self, BinOpKind}; use ext::mtwt; use ptr::P; -use util::interner::StrInterner; +use util::interner::Interner; use tokenstream; use serialize::{Decodable, Decoder, Encodable, Encoder}; @@ -396,7 +396,7 @@ macro_rules! declare_keywords {( } fn mk_fresh_ident_interner() -> IdentInterner { - StrInterner::prefill(&[$($string,)*]) + Interner::prefill(&[$($string,)*]) } }} @@ -472,7 +472,7 @@ declare_keywords! { } // looks like we can get rid of this completely... -pub type IdentInterner = StrInterner; +pub type IdentInterner = Interner; // if an interner exists in TLS, return it. Otherwise, prepare a // fresh one. diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs index 68dbd6272f4..2dd69c76958 100644 --- a/src/libsyntax/util/interner.rs +++ b/src/libsyntax/util/interner.rs @@ -17,122 +17,45 @@ use ast::Name; use std::borrow::Borrow; use std::cell::RefCell; use std::collections::HashMap; -use std::hash::Hash; use std::rc::Rc; -pub struct Interner { - map: RefCell>, - vect: RefCell >, -} - -// when traits can extend traits, we should extend index to get [] -impl Interner { - pub fn new() -> Interner { - Interner { - map: RefCell::new(HashMap::new()), - vect: RefCell::new(Vec::new()), - } - } - - pub fn prefill(init: &[T]) -> Interner { - let rv = Interner::new(); - for v in init { - rv.intern((*v).clone()); - } - rv - } - - pub fn intern(&self, val: T) -> Name { - let mut map = self.map.borrow_mut(); - if let Some(&idx) = (*map).get(&val) { - return idx; - } - - let mut vect = self.vect.borrow_mut(); - let new_idx = Name((*vect).len() as u32); - (*map).insert(val.clone(), new_idx); - (*vect).push(val); - new_idx - } - - pub fn gensym(&self, val: T) -> Name { - let mut vect = self.vect.borrow_mut(); - let new_idx = Name((*vect).len() as u32); - // leave out of .map to avoid colliding - (*vect).push(val); - new_idx - } - - pub fn get(&self, idx: Name) -> T { - let vect = self.vect.borrow(); - (*vect)[idx.0 as usize].clone() - } - - pub fn len(&self) -> usize { - let vect = self.vect.borrow(); - (*vect).len() - } - - pub fn find(&self, val: &Q) -> Option - where T: Borrow, Q: Eq + Hash { - let map = self.map.borrow(); - match (*map).get(val) { - Some(v) => Some(*v), - None => None, - } - } - - pub fn clear(&self) { - *self.map.borrow_mut() = HashMap::new(); - *self.vect.borrow_mut() = Vec::new(); - } -} - -#[derive(Clone, PartialEq, Eq, Hash, Debug)] +#[derive(PartialEq, Eq, Hash)] struct RcStr(Rc); -impl RcStr { - fn new(string: &str) -> Self { - RcStr(Rc::new(string.to_owned())) - } -} - impl Borrow for RcStr { fn borrow(&self) -> &str { &self.0 } } -/// A StrInterner differs from Interner in that it accepts -/// &str rather than RcStr, resulting in less allocation. -pub struct StrInterner { +pub struct Interner { map: RefCell>, vect: RefCell> >, } /// When traits can extend traits, we should extend index to get [] -impl StrInterner { - pub fn new() -> StrInterner { - StrInterner { +impl Interner { + pub fn new() -> Self { + Interner { map: RefCell::new(HashMap::new()), vect: RefCell::new(Vec::new()), } } - pub fn prefill(init: &[&str]) -> StrInterner { - let rv = StrInterner::new(); + pub fn prefill(init: &[&str]) -> Self { + let rv = Interner::new(); for &v in init { rv.intern(v); } rv } - pub fn intern(&self, val: &str) -> Name { + pub fn intern + Into>(&self, val: T) -> Name { let mut map = self.map.borrow_mut(); - if let Some(&idx) = map.get(val) { + if let Some(&idx) = map.get(val.borrow()) { return idx; } let new_idx = Name(self.len() as u32); - let val = Rc::new(val.to_owned()); + let val = Rc::new(val.into()); map.insert(RcStr(val.clone()), new_idx); self.vect.borrow_mut().push(val); new_idx @@ -181,7 +104,7 @@ impl StrInterner { *self.vect.borrow_mut() = Vec::new(); } - pub fn reset(&self, other: StrInterner) { + pub fn reset(&self, other: Interner) { *self.map.borrow_mut() = other.map.into_inner(); *self.vect.borrow_mut() = other.vect.into_inner(); } @@ -190,57 +113,11 @@ impl StrInterner { #[cfg(test)] mod tests { use super::*; - use super::RcStr; use ast::Name; #[test] - #[should_panic] - fn i1 () { - let i : Interner = Interner::new(); - i.get(Name(13)); - } - - #[test] - fn interner_tests () { - let i : Interner = Interner::new(); - // first one is zero: - assert_eq!(i.intern(RcStr::new("dog")), Name(0)); - // re-use gets the same entry: - assert_eq!(i.intern(RcStr::new("dog")), Name(0)); - // different string gets a different #: - assert_eq!(i.intern(RcStr::new("cat")), Name(1)); - assert_eq!(i.intern(RcStr::new("cat")), Name(1)); - // dog is still at zero - assert_eq!(i.intern(RcStr::new("dog")), Name(0)); - // gensym gets 3 - assert_eq!(i.gensym(RcStr::new("zebra") ), Name(2)); - // gensym of same string gets new number : - assert_eq!(i.gensym (RcStr::new("zebra") ), Name(3)); - // gensym of *existing* string gets new number: - assert_eq!(i.gensym(RcStr::new("dog")), Name(4)); - assert_eq!(i.get(Name(0)), RcStr::new("dog")); - assert_eq!(i.get(Name(1)), RcStr::new("cat")); - assert_eq!(i.get(Name(2)), RcStr::new("zebra")); - assert_eq!(i.get(Name(3)), RcStr::new("zebra")); - assert_eq!(i.get(Name(4)), RcStr::new("dog")); - } - - #[test] - fn i3 () { - let i : Interner = Interner::prefill(&[ - RcStr::new("Alan"), - RcStr::new("Bob"), - RcStr::new("Carol") - ]); - assert_eq!(i.get(Name(0)), RcStr::new("Alan")); - assert_eq!(i.get(Name(1)), RcStr::new("Bob")); - assert_eq!(i.get(Name(2)), RcStr::new("Carol")); - assert_eq!(i.intern(RcStr::new("Bob")), Name(1)); - } - - #[test] - fn string_interner_tests() { - let i : StrInterner = StrInterner::new(); + fn interner_tests() { + let i : Interner = Interner::new(); // first one is zero: assert_eq!(i.intern("dog"), Name(0)); // re-use gets the same entry: -- cgit 1.4.1-3-g733a5 From 752d4419a060e007548cf56f85ff864a13589567 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Mon, 11 Jul 2016 19:33:40 +0000 Subject: Refactor `get_ident_interner` -> `with_ident_interner`. --- src/librustc_driver/driver.rs | 4 ++-- src/librustc_metadata/decoder.rs | 4 ++-- src/librustc_trans/trans_item.rs | 5 ++--- src/libsyntax/parse/token.rs | 25 +++++++++++++------------ 4 files changed, 19 insertions(+), 19 deletions(-) (limited to 'src/libsyntax') diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index eef2b6e6f37..ba59c2afc76 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -211,7 +211,7 @@ pub fn compile_input(sess: &Session, } // Discard interned strings as they are no longer required. - token::get_ident_interner().clear(); + token::clear_ident_interner(); Ok((outputs, trans)) })?? @@ -480,7 +480,7 @@ pub fn phase_1_parse_input<'a>(sess: &'a Session, input: &Input) -> PResult<'a, ast::Crate> { // These may be left in an incoherent state after a previous compile. - // `clear_tables` and `get_ident_interner().clear()` can be used to free + // `clear_tables` and `clear_ident_interner` can be used to free // memory, but they do not restore the initial state. syntax::ext::mtwt::reset_tables(); token::reset_ident_interner(); diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 762f3609ac5..3f5c9a6d3bd 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -442,7 +442,7 @@ pub fn get_adt_def<'a, 'tcx>(cdata: Cmd, struct_field_family_to_visibility(ff)) }).chain(reader::tagged_docs(doc, tag_item_unnamed_field).map(|f| { let ff = item_family(f); - let name = token::get_ident_interner().intern(index.to_string()); + let name = token::with_ident_interner(|interner| interner.intern(index.to_string())); index += 1; ty::FieldDefData::new(item_def_id(f, cdata), name, struct_field_family_to_visibility(ff)) @@ -1147,7 +1147,7 @@ pub fn get_struct_field_names(cdata: Cmd, id: DefIndex) -> Vec { reader::tagged_docs(item, tag_item_field).map(|an_item| { item_name(an_item) }).chain(reader::tagged_docs(item, tag_item_unnamed_field).map(|_| { - let name = token::get_ident_interner().intern(index.to_string()); + let name = token::with_ident_interner(|interner| interner.intern(index.to_string())); index += 1; name })).collect() diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index b7b18b2631b..4729a9adcec 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -31,7 +31,6 @@ use rustc::ty::subst; use std::hash::{Hash, Hasher}; use syntax::ast::{self, NodeId}; use syntax::{attr,errors}; -use syntax::parse::token; use type_of; use glue; use abi::{Abi, FnType}; @@ -562,8 +561,8 @@ fn push_type_params<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, for projection in projections { let projection = projection.skip_binder(); - let name = token::get_ident_interner().get(projection.projection_ty.item_name); - output.push_str(&name[..]); + let name = &projection.projection_ty.item_name.as_str(); + output.push_str(name); output.push_str("="); push_unique_type_name(tcx, projection.ty, output); output.push_str(", "); diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 222cf65b78e..c3908118284 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -477,17 +477,20 @@ pub type IdentInterner = Interner; // 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 get_ident_interner() -> Rc { - thread_local!(static KEY: Rc<::parse::token::IdentInterner> = { - Rc::new(mk_fresh_ident_interner()) +pub fn with_ident_interner T>(f: F) -> T { + thread_local!(static KEY: IdentInterner = { + mk_fresh_ident_interner() }); - KEY.with(|k| k.clone()) + KEY.with(f) } /// Reset the ident interner to its initial state. pub fn reset_ident_interner() { - let interner = get_ident_interner(); - interner.reset(mk_fresh_ident_interner()); + with_ident_interner(|interner| interner.reset(mk_fresh_ident_interner())); +} + +pub fn clear_ident_interner() { + with_ident_interner(|interner| interner.clear()); } /// Represents a string stored in the thread-local interner. Because the @@ -521,8 +524,7 @@ impl InternedString { #[inline] pub fn new_from_name(name: ast::Name) -> InternedString { - let interner = get_ident_interner(); - InternedString::new_from_rc_str(interner.get(name)) + with_ident_interner(|interner| InternedString::new_from_rc_str(interner.get(name))) } } @@ -610,13 +612,13 @@ pub fn intern_and_get_ident(s: &str) -> InternedString { /// Maps a string to its interned representation. #[inline] pub fn intern(s: &str) -> ast::Name { - get_ident_interner().intern(s) + with_ident_interner(|interner| interner.intern(s)) } /// gensym's a new usize, using the current interner. #[inline] pub fn gensym(s: &str) -> ast::Name { - get_ident_interner().gensym(s) + with_ident_interner(|interner| interner.gensym(s)) } /// Maps a string to an identifier with an empty syntax context. @@ -635,8 +637,7 @@ pub fn gensym_ident(s: &str) -> ast::Ident { // note that this guarantees that str_ptr_eq(ident_to_string(src),interner_get(fresh_name(src))); // that is, that the new name and the old one are connected to ptr_eq strings. pub fn fresh_name(src: ast::Ident) -> ast::Name { - let interner = get_ident_interner(); - interner.gensym_copy(src.name) + with_ident_interner(|interner| interner.gensym_copy(src.name)) // following: debug version. Could work in final except that it's incompatible with // good error messages and uses of struct names in ambiguous could-be-binding // locations. Also definitely destroys the guarantee given above about ptr_eq. -- cgit 1.4.1-3-g733a5 From 060b5c5ef273a6b74ccbd10c1d4a1debfa27d9de Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Mon, 11 Jul 2016 20:00:07 +0000 Subject: Factor the `RefCell` out of the `Interner`. --- src/libsyntax/parse/token.rs | 13 +++--- src/libsyntax/util/interner.rs | 94 +++++++++++++++--------------------------- 2 files changed, 41 insertions(+), 66 deletions(-) (limited to 'src/libsyntax') diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index c3908118284..ab7ed223bb3 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -21,6 +21,7 @@ use util::interner::Interner; 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 @@ pub type IdentInterner = Interner; // 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: F) -> T { - thread_local!(static KEY: IdentInterner = { - mk_fresh_ident_interner() +pub fn with_ident_interner T>(f: F) -> T { + thread_local!(static KEY: RefCell = { + 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 diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs index 2dd69c76958..6bb409715aa 100644 --- a/src/libsyntax/util/interner.rs +++ b/src/libsyntax/util/interner.rs @@ -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 @@ impl Borrow for RcStr { } } +#[derive(Default)] pub struct Interner { - map: RefCell>, - vect: RefCell> >, + names: HashMap, + strings: Vec>, } /// When traits can extend traits, we should extend index 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 + Into>(&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 + Into>(&mut self, string: T) -> Name { + if let Some(&name) = self.names.get(string.borrow()) { + return name; + } - pub fn get(&self, idx: Name) -> Rc { - (*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 { - 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 { + 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 { + self.names.get(string).cloned() } } @@ -117,7 +91,7 @@ mod tests { #[test] fn interner_tests() { - let i : 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: -- cgit 1.4.1-3-g733a5