Skip to content

Commit 0e27c36

Browse files
committed
Add various comments.
Lots of details I wish I'd known when I first looked at this code.
1 parent c2cae7b commit 0e27c36

File tree

1 file changed

+43
-9
lines changed

1 file changed

+43
-9
lines changed

src/libsyntax_pos/symbol.rs

+43-9
Original file line numberDiff line numberDiff line change
@@ -344,9 +344,22 @@ impl Decodable for Ident {
344344
}
345345
}
346346

347-
/// A symbol is an interned or gensymed string. The use of `newtype_index!` means
348-
/// that `Option<Symbol>` only takes up 4 bytes, because `newtype_index!` reserves
349-
/// the last 256 values for tagging purposes.
347+
/// A symbol is an interned or gensymed string. A gensym is a symbol that is
348+
/// never equal to any other symbol. E.g.:
349+
/// ```
350+
/// assert_eq!(Symbol::intern("x"), Symbol::intern("x"))
351+
/// assert_ne!(Symbol::gensym("x"), Symbol::intern("x"))
352+
/// assert_ne!(Symbol::gensym("x"), Symbol::gensym("x"))
353+
/// ```
354+
/// Conceptually, a gensym can be thought of as a normal symbol with an
355+
/// invisible unique suffix. Gensyms are useful when creating new identifiers
356+
/// that must not match any existing identifiers, e.g. during macro expansion
357+
/// and syntax desugaring.
358+
///
359+
/// Internally, a Symbol is implemented as an index, and all operations
360+
/// (including hashing, equality, and ordering) operate on that index. The use
361+
/// of `newtype_index!` means that `Option<Symbol>` only takes up 4 bytes,
362+
/// because `newtype_index!` reserves the last 256 values for tagging purposes.
350363
///
351364
/// Note that `Symbol` cannot directly be a `newtype_index!` because it implements
352365
/// `fmt::Debug`, `Encodable`, and `Decodable` in special ways.
@@ -380,6 +393,7 @@ impl Symbol {
380393
with_interner(|interner| interner.gensymed(self))
381394
}
382395

396+
// WARNING: this function is deprecated and will be removed in the future.
383397
pub fn is_gensymed(self) -> bool {
384398
with_interner(|interner| interner.is_gensymed(self))
385399
}
@@ -510,6 +524,8 @@ impl Interner {
510524
symbol.0.as_usize() >= self.strings.len()
511525
}
512526

527+
// Get the symbol as a string. `Symbol::as_str()` should be used in
528+
// preference to this function.
513529
pub fn get(&self, symbol: Symbol) -> &str {
514530
match self.strings.get(symbol.0.as_usize()) {
515531
Some(string) => string,
@@ -614,11 +630,17 @@ fn with_interner<T, F: FnOnce(&mut Interner) -> T>(f: F) -> T {
614630
GLOBALS.with(|globals| f(&mut *globals.symbol_interner.lock()))
615631
}
616632

617-
/// Represents a string stored in the interner. Because the interner outlives any thread
618-
/// which uses this type, we can safely treat `string` which points to interner data,
619-
/// as an immortal string, as long as this type never crosses between threads.
620-
// FIXME: ensure that the interner outlives any thread which uses `LocalInternedString`,
621-
// by creating a new thread right after constructing the interner.
633+
/// An alternative to `Symbol` and `InternedString`, useful when the chars
634+
/// within the symbol need to be accessed. It is best used for temporary
635+
/// values.
636+
///
637+
/// Because the interner outlives any thread which uses this type, we can
638+
/// safely treat `string` which points to interner data, as an immortal string,
639+
/// as long as this type never crosses between threads.
640+
//
641+
// FIXME: ensure that the interner outlives any thread which uses
642+
// `LocalInternedString`, by creating a new thread right after constructing the
643+
// interner.
622644
#[derive(Clone, Copy, Hash, PartialOrd, Eq, Ord)]
623645
pub struct LocalInternedString {
624646
string: &'static str,
@@ -711,7 +733,19 @@ impl Encodable for LocalInternedString {
711733
}
712734
}
713735

714-
/// Represents a string stored in the string interner.
736+
/// An alternative to `Symbol` that is focused on string contents. It has two
737+
/// main differences to `Symbol`.
738+
///
739+
/// First, its implementations of `Hash`, `PartialOrd` and `Ord` work with the
740+
/// string chars rather than the symbol integer. This is useful when hash
741+
/// stability is required across compile sessions, or a guaranteed sort
742+
/// ordering is required.
743+
///
744+
/// Second, gensym-ness is irrelevant. E.g.:
745+
/// ```
746+
/// assert_ne!(Symbol::gensym("x"), Symbol::gensym("x"))
747+
/// assert_eq!(Symbol::gensym("x").as_interned_str(), Symbol::gensym("x").as_interned_str())
748+
/// ```
715749
#[derive(Clone, Copy, Eq)]
716750
pub struct InternedString {
717751
symbol: Symbol,

0 commit comments

Comments
 (0)