@@ -630,10 +630,12 @@ pub struct Ident {
630
630
631
631
impl Ident {
632
632
#[ inline]
633
+ /// Constructs a new identifier from a symbol and a span.
633
634
pub const fn new ( name : Symbol , span : Span ) -> Ident {
634
635
Ident { name, span }
635
636
}
636
637
638
+ /// Constructs a new identifier with an empty syntax context.
637
639
#[ inline]
638
640
pub const fn with_empty_ctxt ( name : Symbol ) -> Ident {
639
641
Ident :: new ( name, DUMMY_SP )
@@ -644,11 +646,16 @@ impl Ident {
644
646
Ident :: with_empty_ctxt ( string. as_symbol ( ) )
645
647
}
646
648
647
- /// Maps a string to an identifier with an empty syntax context .
649
+ /// Maps a string to an identifier with an empty span .
648
650
pub fn from_str ( string : & str ) -> Ident {
649
651
Ident :: with_empty_ctxt ( Symbol :: intern ( string) )
650
652
}
651
653
654
+ /// Maps a string and a span to an identifier.
655
+ pub fn from_str_and_span ( string : & str , span : Span ) -> Ident {
656
+ Ident :: new ( Symbol :: intern ( string) , span)
657
+ }
658
+
652
659
/// Replaces `lo` and `hi` with those from `span`, but keep hygiene context.
653
660
pub fn with_span_pos ( self , span : Span ) -> Ident {
654
661
Ident :: new ( self . name , span. with_ctxt ( self . span . ctxt ( ) ) )
@@ -676,11 +683,14 @@ impl Ident {
676
683
Ident :: new ( self . name , self . span . modern_and_legacy ( ) )
677
684
}
678
685
686
+ /// Transforms an identifier into one with the same name, but gensymed.
679
687
pub fn gensym ( self ) -> Ident {
680
688
let name = with_interner ( |interner| interner. gensymed ( self . name ) ) ;
681
689
Ident :: new ( name, self . span )
682
690
}
683
691
692
+ /// Transforms an underscore identifier into one with the same name, but
693
+ /// gensymed. Leaves non-underscore identifiers unchanged.
684
694
pub fn gensym_if_underscore ( self ) -> Ident {
685
695
if self . name == keywords:: Underscore . name ( ) { self . gensym ( ) } else { self }
686
696
}
@@ -742,30 +752,34 @@ impl Decodable for Ident {
742
752
Ok ( if !string. starts_with ( '#' ) {
743
753
Ident :: from_str ( & string)
744
754
} else { // FIXME(jseyfried): intercrate hygiene
745
- Ident :: with_empty_ctxt ( Symbol :: gensym ( & string[ 1 ..] ) )
755
+ Ident :: from_str ( & string[ 1 ..] ) . gensym ( )
746
756
} )
747
757
}
748
758
}
749
759
750
760
/// A symbol is an interned or gensymed string. A gensym is a symbol that is
751
- /// never equal to any other symbol. E.g.:
752
- /// ```
753
- /// assert_eq!(Symbol::intern("x"), Symbol::intern("x"))
754
- /// assert_ne!(Symbol::gensym("x"), Symbol::intern("x"))
755
- /// assert_ne!(Symbol::gensym("x"), Symbol::gensym("x"))
756
- /// ```
761
+ /// never equal to any other symbol.
762
+ ///
757
763
/// Conceptually, a gensym can be thought of as a normal symbol with an
758
764
/// invisible unique suffix. Gensyms are useful when creating new identifiers
759
765
/// that must not match any existing identifiers, e.g. during macro expansion
760
- /// and syntax desugaring.
766
+ /// and syntax desugaring. Because gensyms should always be identifiers, all
767
+ /// gensym operations are on `Ident` rather than `Symbol`. (Indeed, in the
768
+ /// future the gensym-ness may be moved from `Symbol` to hygiene data.)
761
769
///
762
- /// Internally, a Symbol is implemented as an index, and all operations
770
+ /// Examples:
771
+ /// ```
772
+ /// assert_eq!(Ident::from_str("x"), Ident::from_str("x"))
773
+ /// assert_ne!(Ident::from_str("x").gensym(), Ident::from_str("x"))
774
+ /// assert_ne!(Ident::from_str("x").gensym(), Ident::from_str("x").gensym())
775
+ /// ```
776
+ /// Internally, a symbol is implemented as an index, and all operations
763
777
/// (including hashing, equality, and ordering) operate on that index. The use
764
778
/// of `newtype_index!` means that `Option<Symbol>` only takes up 4 bytes,
765
779
/// because `newtype_index!` reserves the last 256 values for tagging purposes.
766
780
///
767
- /// Note that `Symbol` cannot directly be a `newtype_index!` because it implements
768
- /// `fmt::Debug`, `Encodable`, and `Decodable` in special ways.
781
+ /// Note that `Symbol` cannot directly be a `newtype_index!` because it
782
+ /// implements `fmt::Debug`, `Encodable`, and `Decodable` in special ways.
769
783
#[ derive( Clone , Copy , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
770
784
pub struct Symbol ( SymbolIndex ) ;
771
785
@@ -783,11 +797,6 @@ impl Symbol {
783
797
with_interner ( |interner| interner. intern ( string) )
784
798
}
785
799
786
- /// Gensyms a new `usize`, using the current interner.
787
- pub fn gensym ( string : & str ) -> Self {
788
- with_interner ( |interner| interner. gensym ( string) )
789
- }
790
-
791
800
pub fn as_str ( self ) -> LocalInternedString {
792
801
with_interner ( |interner| unsafe {
793
802
LocalInternedString {
@@ -895,11 +904,6 @@ impl Interner {
895
904
}
896
905
}
897
906
898
- fn gensym ( & mut self , string : & str ) -> Symbol {
899
- let symbol = self . intern ( string) ;
900
- self . gensymed ( symbol)
901
- }
902
-
903
907
fn gensymed ( & mut self , symbol : Symbol ) -> Symbol {
904
908
self . gensyms . push ( symbol) ;
905
909
Symbol :: new ( SymbolIndex :: MAX_AS_U32 - self . gensyms . len ( ) as u32 + 1 )
@@ -1267,11 +1271,13 @@ mod tests {
1267
1271
assert_eq ! ( i. intern( "cat" ) , Symbol :: new( 1 ) ) ;
1268
1272
// dog is still at zero
1269
1273
assert_eq ! ( i. intern( "dog" ) , Symbol :: new( 0 ) ) ;
1270
- assert_eq ! ( i. gensym( "zebra" ) , Symbol :: new( SymbolIndex :: MAX_AS_U32 ) ) ;
1274
+ let z = i. intern ( "zebra" ) ;
1275
+ assert_eq ! ( i. gensymed( z) , Symbol :: new( SymbolIndex :: MAX_AS_U32 ) ) ;
1271
1276
// gensym of same string gets new number:
1272
- assert_eq ! ( i. gensym ( "zebra" ) , Symbol :: new( SymbolIndex :: MAX_AS_U32 - 1 ) ) ;
1277
+ assert_eq ! ( i. gensymed ( z ) , Symbol :: new( SymbolIndex :: MAX_AS_U32 - 1 ) ) ;
1273
1278
// gensym of *existing* string gets new number:
1274
- assert_eq ! ( i. gensym( "dog" ) , Symbol :: new( SymbolIndex :: MAX_AS_U32 - 2 ) ) ;
1279
+ let d = i. intern ( "dog" ) ;
1280
+ assert_eq ! ( i. gensymed( d) , Symbol :: new( SymbolIndex :: MAX_AS_U32 - 2 ) ) ;
1275
1281
}
1276
1282
1277
1283
#[ test]
0 commit comments