@@ -344,9 +344,18 @@ impl Decodable for Ident {
344
344
}
345
345
}
346
346
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 special kind of
348
+ /// symbol that is never equal to any other symbol. E.g.:
349
+ /// - `Symbol::intern("x") == Symbol::intern("x")`
350
+ /// - `Symbol::gensym("x") != Symbol::intern("x")`
351
+ /// - `Symbol::gensym("x") != Symbol::gensym("x")`
352
+ ///
353
+ /// Gensyms are useful when creating new identifiers that must not match any
354
+ /// existing identifiers during macro expansion and syntax desugaring.)
355
+ ///
356
+ /// The use of `newtype_index!` means that `Option<Symbol>` only takes up 4
357
+ /// bytes, because `newtype_index!` reserves the last 256 values for tagging
358
+ /// purposes.
350
359
///
351
360
/// Note that `Symbol` cannot directly be a `newtype_index!` because it implements
352
361
/// `fmt::Debug`, `Encodable`, and `Decodable` in special ways.
@@ -387,7 +396,7 @@ impl Symbol {
387
396
pub fn as_str ( self ) -> LocalInternedString {
388
397
with_interner ( |interner| unsafe {
389
398
LocalInternedString {
390
- string : std:: mem:: transmute :: < & str , & str > ( interner. get ( self ) )
399
+ string : std:: mem:: transmute :: < & str , & str > ( interner. symbol_or_gensym_str ( self ) )
391
400
}
392
401
} )
393
402
}
@@ -510,7 +519,13 @@ impl Interner {
510
519
symbol. 0 . as_usize ( ) >= self . strings . len ( )
511
520
}
512
521
513
- pub fn get ( & self , symbol : Symbol ) -> & str {
522
+ /// Get the chars of a normal (non-gensym) symbol.
523
+ pub fn symbol_str ( & self , symbol : Symbol ) -> & str {
524
+ self . strings [ symbol. 0 . as_usize ( ) ]
525
+ }
526
+
527
+ /// Get the chars of a normal or gensym symbol.
528
+ fn symbol_or_gensym_str ( & self , symbol : Symbol ) -> & str {
514
529
match self . strings . get ( symbol. 0 . as_usize ( ) ) {
515
530
Some ( string) => string,
516
531
None => {
@@ -614,11 +629,17 @@ fn with_interner<T, F: FnOnce(&mut Interner) -> T>(f: F) -> T {
614
629
GLOBALS . with ( |globals| f ( & mut * globals. symbol_interner . lock ( ) ) )
615
630
}
616
631
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.
632
+ /// An alternative to `Symbol` and `LocalInternedString`, useful when the chars
633
+ /// within the symbol need to be accessed. It is best used for temporary
634
+ /// values.
635
+ ///
636
+ /// Because the interner outlives any thread which uses this type, we can
637
+ /// safely treat `string` which points to interner data, as an immortal string,
638
+ /// as long as this type never crosses between threads.
639
+ //
640
+ // FIXME: ensure that the interner outlives any thread which uses
641
+ // `LocalInternedString`, by creating a new thread right after constructing the
642
+ // interner.
622
643
#[ derive( Clone , Copy , Hash , PartialOrd , Eq , Ord ) ]
623
644
pub struct LocalInternedString {
624
645
string : & ' static str ,
@@ -711,7 +732,12 @@ impl Encodable for LocalInternedString {
711
732
}
712
733
}
713
734
714
- /// Represents a string stored in the string interner.
735
+ /// A thin wrapper around `Symbol`. It has two main differences to `Symbol`.
736
+ /// - Its implementations of `Hash`, `PartialOrd` and `Ord` work with the
737
+ /// string chars rather than the symbol integer. This is useful when
738
+ /// hash stability is required across compile sessions, or a guaranteed sort
739
+ /// ordering is required.
740
+ /// - It is guaranteed to not be a gensym symbol.
715
741
#[ derive( Clone , Copy , Eq ) ]
716
742
pub struct InternedString {
717
743
symbol : Symbol ,
@@ -720,7 +746,7 @@ pub struct InternedString {
720
746
impl InternedString {
721
747
pub fn with < F : FnOnce ( & str ) -> R , R > ( self , f : F ) -> R {
722
748
let str = with_interner ( |interner| {
723
- interner. get ( self . symbol ) as * const str
749
+ interner. symbol_str ( self . symbol ) as * const str
724
750
} ) ;
725
751
// This is safe because the interner keeps string alive until it is dropped.
726
752
// We can access it because we know the interner is still alive since we use a
@@ -730,8 +756,8 @@ impl InternedString {
730
756
731
757
pub fn with2 < F : FnOnce ( & str , & str ) -> R , R > ( self , other : & InternedString , f : F ) -> R {
732
758
let ( self_str, other_str) = with_interner ( |interner| {
733
- ( interner. get ( self . symbol ) as * const str ,
734
- interner. get ( other. symbol ) as * const str )
759
+ ( interner. symbol_str ( self . symbol ) as * const str ,
760
+ interner. symbol_str ( other. symbol ) as * const str )
735
761
} ) ;
736
762
// This is safe for the same reason that `with` is safe.
737
763
unsafe { f ( & * self_str, & * other_str) }
0 commit comments