Skip to content

Commit

Permalink
Remove gensyms
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewjasper committed Oct 15, 2019
1 parent 1a2597b commit 94967f2
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 88 deletions.
90 changes: 9 additions & 81 deletions src/libsyntax_pos/symbol.rs
Expand Up @@ -807,25 +807,13 @@ impl Ident {
Ident::new(self.name, self.span.modern_and_legacy())
}

/// Transforms an underscore identifier into one with the same name, but
/// gensymed. Leaves non-underscore identifiers unchanged.
pub fn gensym_if_underscore(self) -> Ident {
if self.name == kw::Underscore {
let name = with_interner(|interner| interner.gensymed(self.name));
Ident::new(name, self.span)
} else {
self
}
}

/// Convert the name to a `LocalInternedString`. This is a slowish
/// operation because it requires locking the symbol interner.
pub fn as_str(self) -> LocalInternedString {
self.name.as_str()
}

/// Convert the name to an `InternedString`. This is a slowish operation
/// because it requires locking the symbol interner.
/// Convert the name to an `InternedString`.
pub fn as_interned_str(self) -> InternedString {
self.name.as_interned_str()
}
Expand Down Expand Up @@ -880,26 +868,9 @@ impl UseSpecializedDecodable for Ident {
}
}

/// A symbol is an interned or gensymed string. A gensym is a symbol that is
/// never equal to any other symbol.
/// An interned string.
///
/// Conceptually, a gensym can be thought of as a normal symbol with an
/// invisible unique suffix. Gensyms are useful when creating new identifiers
/// that must not match any existing identifiers, e.g. during macro expansion
/// and syntax desugaring. Because gensyms should always be identifiers, all
/// gensym operations are on `Ident` rather than `Symbol`. (Indeed, in the
/// future the gensym-ness may be moved from `Symbol` to hygiene data.)
///
/// Examples:
/// ```
/// assert_eq!(Ident::from_str("_"), Ident::from_str("_"))
/// assert_ne!(Ident::from_str("_").gensym_if_underscore(), Ident::from_str("_"))
/// assert_ne!(
/// Ident::from_str("_").gensym_if_underscore(),
/// Ident::from_str("_").gensym_if_underscore(),
/// )
/// ```
/// Internally, a symbol is implemented as an index, and all operations
/// Internally, a `Symbol` is implemented as an index, and all operations
/// (including hashing, equality, and ordering) operate on that index. The use
/// of `rustc_index::newtype_index!` means that `Option<Symbol>` only takes up 4 bytes,
/// because `rustc_index::newtype_index!` reserves the last 256 values for tagging purposes.
Expand Down Expand Up @@ -950,12 +921,9 @@ impl Symbol {
})
}

/// Convert to an `InternedString`. This is a slowish operation because it
/// requires locking the symbol interner.
/// Convert to an `InternedString`.
pub fn as_interned_str(self) -> InternedString {
with_interner(|interner| InternedString {
symbol: interner.interned(self)
})
InternedString { symbol: self }
}

pub fn as_u32(self) -> u32 {
Expand All @@ -965,12 +933,7 @@ impl Symbol {

impl fmt::Debug for Symbol {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let is_gensymed = with_interner(|interner| interner.is_gensymed(*self));
if is_gensymed {
write!(f, "{}({:?})", self, self.0)
} else {
write!(f, "{}", self)
}
fmt::Display::fmt(self, f)
}
}

Expand All @@ -993,15 +956,11 @@ impl Decodable for Symbol {
}

// The `&'static str`s in this type actually point into the arena.
//
// Note that normal symbols are indexed upward from 0, and gensyms are indexed
// downward from SymbolIndex::MAX_AS_U32.
#[derive(Default)]
pub struct Interner {
arena: DroplessArena,
names: FxHashMap<&'static str, Symbol>,
strings: Vec<&'static str>,
gensyms: Vec<Symbol>,
}

impl Interner {
Expand Down Expand Up @@ -1034,34 +993,10 @@ impl Interner {
self.names.insert(string, name);
name
}

fn interned(&self, symbol: Symbol) -> Symbol {
if (symbol.0.as_usize()) < self.strings.len() {
symbol
} else {
self.gensyms[(SymbolIndex::MAX_AS_U32 - symbol.0.as_u32()) as usize]
}
}

fn gensymed(&mut self, symbol: Symbol) -> Symbol {
self.gensyms.push(symbol);
Symbol::new(SymbolIndex::MAX_AS_U32 - self.gensyms.len() as u32 + 1)
}

fn is_gensymed(&mut self, symbol: Symbol) -> bool {
symbol.0.as_usize() >= self.strings.len()
}

// Get the symbol as a string. `Symbol::as_str()` should be used in
// preference to this function.
pub fn get(&self, symbol: Symbol) -> &str {
match self.strings.get(symbol.0.as_usize()) {
Some(string) => string,
None => {
let symbol = self.gensyms[(SymbolIndex::MAX_AS_U32 - symbol.0.as_u32()) as usize];
self.strings[symbol.0.as_usize()]
}
}
self.strings[symbol.0.as_usize()]
}
}

Expand Down Expand Up @@ -1246,19 +1181,12 @@ impl fmt::Display for LocalInternedString {
}
}

/// An alternative to `Symbol` that is focused on string contents. It has two
/// main differences to `Symbol`.
/// An alternative to `Symbol` that is focused on string contents.
///
/// First, its implementations of `Hash`, `PartialOrd` and `Ord` work with the
/// Its implementations of `Hash`, `PartialOrd` and `Ord` work with the
/// string chars rather than the symbol integer. This is useful when hash
/// stability is required across compile sessions, or a guaranteed sort
/// ordering is required.
///
/// Second, gensym-ness is irrelevant. E.g.:
/// ```
/// assert_ne!(Symbol::gensym("x"), Symbol::gensym("x"))
/// assert_eq!(Symbol::gensym("x").as_interned_str(), Symbol::gensym("x").as_interned_str())
/// ```
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct InternedString {
symbol: Symbol,
Expand Down
7 changes: 0 additions & 7 deletions src/libsyntax_pos/symbol/tests.rs
Expand Up @@ -14,13 +14,6 @@ fn interner_tests() {
assert_eq!(i.intern("cat"), Symbol::new(1));
// dog is still at zero
assert_eq!(i.intern("dog"), Symbol::new(0));
let z = i.intern("zebra");
assert_eq!(i.gensymed(z), Symbol::new(SymbolIndex::MAX_AS_U32));
// gensym of same string gets new number:
assert_eq!(i.gensymed(z), Symbol::new(SymbolIndex::MAX_AS_U32 - 1));
// gensym of *existing* string gets new number:
let d = i.intern("dog");
assert_eq!(i.gensymed(d), Symbol::new(SymbolIndex::MAX_AS_U32 - 2));
}

#[test]
Expand Down

0 comments on commit 94967f2

Please sign in to comment.