1use crate::{Session, SessionGlobals, Span};
2use solar_data_structures::{index::NonMaxU32, trustme};
3use solar_macros::symbols;
4use std::{cmp, fmt, hash, str};
5
6#[derive(Clone, Copy)]
8pub struct Ident {
9 pub name: Symbol,
11 pub span: Span,
13}
14
15impl Default for Ident {
16 #[inline]
17 fn default() -> Self {
18 Self::DUMMY
19 }
20}
21
22impl PartialEq for Ident {
23 #[inline]
24 fn eq(&self, rhs: &Self) -> bool {
25 self.name == rhs.name
26 }
27}
28
29impl Eq for Ident {}
30
31impl PartialOrd for Ident {
32 #[inline]
33 fn partial_cmp(&self, rhs: &Self) -> Option<cmp::Ordering> {
34 Some(self.cmp(rhs))
35 }
36}
37
38impl Ord for Ident {
39 #[inline]
40 fn cmp(&self, rhs: &Self) -> cmp::Ordering {
41 self.name.cmp(&rhs.name)
42 }
43}
44
45impl hash::Hash for Ident {
46 #[inline]
47 fn hash<H: hash::Hasher>(&self, state: &mut H) {
48 self.name.hash(state);
49 }
50}
51
52impl fmt::Debug for Ident {
53 #[inline]
54 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55 fmt::Display::fmt(self, f)
56 }
57}
58
59impl fmt::Display for Ident {
60 #[inline]
61 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62 self.name.fmt(f)
63 }
64}
65
66impl Ident {
67 pub const DUMMY: Self = Self::new(Symbol::DUMMY, Span::DUMMY);
69
70 #[inline]
72 pub const fn new(name: Symbol, span: Span) -> Self {
73 Self { name, span }
74 }
75
76 #[inline]
78 pub const fn with_dummy_span(name: Symbol) -> Self {
79 Self::new(name, Span::DUMMY)
80 }
81
82 #[allow(clippy::should_implement_trait)]
84 pub fn from_str(string: &str) -> Self {
85 Self::with_dummy_span(Symbol::intern(string))
86 }
87
88 pub fn from_str_and_span(string: &str, span: Span) -> Self {
90 Self::new(Symbol::intern(string), span)
91 }
92
93 #[inline]
95 #[allow(clippy::inherent_to_string_shadow_display)]
96 #[cfg_attr(debug_assertions, track_caller)]
97 pub fn to_string(&self) -> String {
98 self.as_str().to_string()
99 }
100
101 #[cfg_attr(debug_assertions, track_caller)]
105 pub fn as_str(&self) -> &str {
106 self.name.as_str()
107 }
108
109 #[inline]
113 #[cfg_attr(debug_assertions, track_caller)]
114 pub fn as_str_in(self, session: &Session) -> &str {
115 self.name.as_str_in(session)
116 }
117
118 #[inline]
120 pub fn is_used_keyword(self) -> bool {
121 self.name.is_used_keyword()
122 }
123
124 #[inline]
126 pub fn is_unused_keyword(self) -> bool {
127 self.name.is_unused_keyword()
128 }
129
130 #[inline]
132 pub fn is_weak_keyword(self) -> bool {
133 self.name.is_weak_keyword()
134 }
135
136 #[inline]
138 pub fn is_yul_keyword(self) -> bool {
139 self.name.is_yul_keyword()
140 }
141
142 #[inline]
144 pub fn is_yul_builtin(self) -> bool {
145 self.name.is_yul_builtin()
146 }
147
148 #[inline]
150 pub fn is_reserved_yul_builtin(self) -> bool {
151 self.name.is_reserved_yul_builtin()
152 }
153
154 #[inline]
157 pub fn is_reserved(self, yul: bool) -> bool {
158 self.name.is_reserved(yul)
159 }
160
161 #[inline]
164 pub fn is_non_reserved(self, yul: bool) -> bool {
165 self.name.is_non_reserved(yul)
166 }
167
168 #[inline]
172 pub fn is_elementary_type(self) -> bool {
173 self.name.is_elementary_type()
174 }
175
176 #[inline]
178 pub fn is_bool_lit(self) -> bool {
179 self.name.is_bool_lit()
180 }
181
182 #[inline]
184 pub fn is_location_specifier(self) -> bool {
185 self.name.is_location_specifier()
186 }
187
188 #[inline]
190 pub fn is_mutability_specifier(self) -> bool {
191 self.name.is_mutability_specifier()
192 }
193
194 #[inline]
196 pub fn is_visibility_specifier(self) -> bool {
197 self.name.is_visibility_specifier()
198 }
199}
200
201#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
206pub struct Symbol(NonMaxU32);
207
208impl Default for Symbol {
209 #[inline]
210 fn default() -> Self {
211 Self::DUMMY
212 }
213}
214
215impl Symbol {
216 pub const DUMMY: Self = kw::Empty;
218
219 const fn new(n: u32) -> Self {
220 Self(NonMaxU32::new(n).unwrap())
221 }
222
223 pub fn intern(string: &str) -> Self {
225 SessionGlobals::with(|g| g.symbol_interner.intern(string))
226 }
227
228 #[inline]
230 pub fn intern_in(string: &str, session: &Session) -> Self {
231 session.intern(string)
232 }
233
234 #[inline]
236 #[allow(clippy::inherent_to_string_shadow_display)]
237 pub fn to_string(&self) -> String {
238 self.as_str().to_string()
239 }
240
241 #[cfg_attr(debug_assertions, track_caller)]
249 pub fn as_str(&self) -> &str {
250 SessionGlobals::with(|g| unsafe { trustme::decouple_lt(g.symbol_interner.get(*self)) })
251 }
252
253 #[inline]
257 #[cfg_attr(debug_assertions, track_caller)]
258 pub fn as_str_in(self, session: &Session) -> &str {
259 session.resolve_symbol(self)
260 }
261
262 #[inline(always)]
264 pub const fn as_u32(self) -> u32 {
265 self.0.get()
266 }
267
268 #[inline]
272 pub fn is_used_keyword(self) -> bool {
273 self < kw::After
274 }
275
276 #[inline]
278 pub fn is_unused_keyword(self) -> bool {
279 self >= kw::After && self <= kw::Var
280 }
281
282 #[inline]
284 pub fn is_weak_keyword(self) -> bool {
285 self >= kw::Leave && self <= kw::Builtin
286 }
287
288 #[inline]
290 pub fn is_yul_keyword(self) -> bool {
291 matches!(
293 self,
294 kw::Function
295 | kw::Let
296 | kw::If
297 | kw::Switch
298 | kw::Case
299 | kw::Default
300 | kw::For
301 | kw::Break
302 | kw::Continue
303 | kw::Leave
304 | kw::True
305 | kw::False
306 )
307 }
308
309 #[inline]
311 pub fn is_yul_builtin(self) -> bool {
312 (self >= kw::Add && self <= kw::Xor)
313 || (self >= kw::Auxdataloadn && self <= kw::Setimmutable)
314 || matches!(self, kw::Address | kw::Byte | kw::Return | kw::Revert)
315 }
316
317 #[inline]
319 pub fn is_reserved_yul_builtin(self) -> bool {
320 (self >= kw::Add && self <= kw::Xor)
321 || matches!(self, kw::Address | kw::Byte | kw::Return | kw::Revert)
322 }
323
324 #[inline]
327 pub fn is_reserved(self, yul: bool) -> bool {
328 if yul {
329 self.is_yul_keyword() | self.is_reserved_yul_builtin()
330 } else {
331 self.is_used_keyword() | self.is_unused_keyword()
332 }
333 }
334
335 #[inline]
338 pub fn is_non_reserved(self, yul: bool) -> bool {
339 !self.is_reserved(yul)
340 }
341
342 #[inline]
346 pub fn is_elementary_type(self) -> bool {
347 self >= kw::Int && self <= kw::UFixed
348 }
349
350 #[inline]
352 pub fn is_bool_lit(self) -> bool {
353 self == kw::False || self == kw::True
354 }
355
356 #[inline]
358 pub fn is_location_specifier(self) -> bool {
359 matches!(self, kw::Calldata | kw::Memory | kw::Storage)
360 }
361
362 #[inline]
364 pub fn is_mutability_specifier(self) -> bool {
365 matches!(self, kw::Immutable | kw::Constant)
366 }
367
368 #[inline]
370 pub fn is_visibility_specifier(self) -> bool {
371 matches!(self, kw::Public | kw::Private | kw::Internal | kw::External)
372 }
373
374 #[inline]
376 pub const fn is_preinterned(self) -> bool {
377 self.as_u32() < PREINTERNED_SYMBOLS_COUNT
378 }
379}
380
381impl fmt::Debug for Symbol {
382 #[inline]
383 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
384 fmt::Debug::fmt(self.as_str(), f)
385 }
386}
387
388impl fmt::Display for Symbol {
389 #[inline]
390 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
391 fmt::Display::fmt(self.as_str(), f)
392 }
393}
394
395#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
399pub struct ByteSymbol(NonMaxU32);
400
401impl ByteSymbol {
402 pub fn intern(byte_str: &[u8]) -> Self {
404 SessionGlobals::with(|g| g.symbol_interner.intern_byte_str(byte_str))
405 }
406
407 #[cfg_attr(debug_assertions, track_caller)]
411 pub fn as_byte_str(&self) -> &[u8] {
412 SessionGlobals::with(|g| unsafe {
413 trustme::decouple_lt(g.symbol_interner.get_byte_str(*self))
414 })
415 }
416
417 #[cfg_attr(debug_assertions, track_caller)]
421 pub fn as_byte_str_in(self, session: &Session) -> &[u8] {
422 session.resolve_byte_str(self)
423 }
424
425 #[inline(always)]
427 pub fn as_u32(self) -> u32 {
428 self.0.get()
429 }
430}
431
432impl fmt::Debug for ByteSymbol {
433 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
434 fmt::Debug::fmt(self.as_byte_str(), f)
435 }
436}
437
438pub(crate) struct Interner {
442 inner: inturn::sync::BytesInterner<ByteSymbol, solar_data_structures::map::FxBuildHasher>,
443}
444
445impl Interner {
446 pub(crate) fn fresh() -> Self {
447 Self::prefill(PREINTERNED)
448 }
449
450 pub(crate) fn prefill(init: &[&'static str]) -> Self {
451 let mut inner = inturn::sync::BytesInterner::with_capacity_and_hasher(
452 init.len() * 4,
453 Default::default(),
454 );
455 inner.intern_many_mut_static(init.iter().map(|s| s.as_bytes()));
456 Self { inner }
457 }
458
459 #[inline]
460 pub(crate) fn intern(&self, string: &str) -> Symbol {
461 Symbol(self.inner.intern(string.as_bytes()).0)
462 }
463
464 #[inline]
465 #[cfg_attr(debug_assertions, track_caller)]
466 pub(crate) fn get(&self, symbol: Symbol) -> &str {
467 let s = self.inner.resolve(ByteSymbol(symbol.0));
468 unsafe { std::str::from_utf8_unchecked(s) }
470 }
471
472 #[inline]
473 pub(crate) fn intern_byte_str(&self, byte_str: &[u8]) -> ByteSymbol {
474 self.inner.intern(byte_str)
475 }
476
477 #[inline]
478 #[cfg_attr(debug_assertions, track_caller)]
479 pub(crate) fn get_byte_str(&self, symbol: ByteSymbol) -> &[u8] {
480 self.inner.resolve(symbol)
481 }
482
483 fn trace_stats(&mut self) {
484 if enabled!(tracing::Level::TRACE) {
485 self.trace_stats_impl();
486 }
487 }
488
489 #[inline(never)]
490 fn trace_stats_impl(&mut self) {
491 let mut lengths = self.inner.iter().map(|(_, s)| s.len()).collect::<Vec<_>>();
492 lengths.sort_unstable();
493 let len = lengths.len();
494 assert!(len > 0);
495 let bytes = lengths.iter().copied().sum::<usize>();
496 trace!(
497 preinterned=PREINTERNED_SYMBOLS_COUNT,
498 len,
499 bytes,
500 max=lengths.last().copied().unwrap_or(0),
501 mean=%format!("{:.2}", (bytes as f64 / len as f64)),
502 median=%format!("{:.2}", if len.is_multiple_of(2) {
503 (lengths[len / 2 - 1] + lengths[len / 2]) as f64 / 2.0
504 } else {
505 lengths[len / 2] as f64
506 }),
507 "Interner stats",
508 );
509 }
510}
511
512impl inturn::InternerSymbol for ByteSymbol {
513 #[inline]
514 fn try_from_usize(n: usize) -> Option<Self> {
515 u32::try_from(n).ok().and_then(NonMaxU32::new).map(Self)
516 }
517
518 #[inline]
519 fn to_usize(self) -> usize {
520 self.0.get() as usize
521 }
522}
523
524impl Drop for Interner {
525 fn drop(&mut self) {
526 self.trace_stats();
527 }
528}
529
530pub mod kw {
536 use crate::Symbol;
537
538 #[doc(inline)]
539 pub use super::kw_generated::*;
540
541 #[inline]
543 pub const fn boolean(b: bool) -> Symbol {
544 if b { True } else { False }
545 }
546
547 #[inline]
555 #[track_caller]
556 pub const fn int(n: u8) -> Symbol {
557 assert!(n <= 32);
558 Symbol::new(Int.as_u32() + n as u32)
559 }
560
561 #[inline]
569 #[track_caller]
570 pub const fn uint(n: u8) -> Symbol {
571 assert!(n <= 32);
572 Symbol::new(UInt.as_u32() + n as u32)
573 }
574
575 #[inline]
581 #[track_caller]
582 pub const fn fixed_bytes(n: u8) -> Symbol {
583 assert!(n > 0 && n <= 32);
584 Symbol::new(Bytes.as_u32() + n as u32)
585 }
586}
587
588pub mod sym {
594 use super::Symbol;
595
596 #[doc(inline)]
597 pub use super::sym_generated::*;
598
599 pub fn integer<N: TryInto<usize> + Copy + itoa::Integer>(n: N) -> Symbol {
603 if let Ok(idx @ 0..=9) = n.try_into() {
604 return Symbol::new(super::SYMBOL_DIGITS_BASE + idx as u32);
605 }
606 Symbol::intern(itoa::Buffer::new().format(n))
607 }
608}
609
610symbols! {
612 Keywords {
616 Empty: "",
618
619 Abstract: "abstract",
620 Anonymous: "anonymous",
621 As: "as",
622 Assembly: "assembly",
623 Break: "break",
624 Calldata: "calldata",
625 Catch: "catch",
626 Constant: "constant",
627 Constructor: "constructor",
628 Continue: "continue",
629 Contract: "contract",
630 Delete: "delete",
631 Do: "do",
632 Else: "else",
633 Emit: "emit",
634 Enum: "enum",
635 Event: "event",
636 External: "external",
637 Fallback: "fallback",
638 For: "for",
639 Function: "function",
640 Hex: "hex",
641 If: "if",
642 Immutable: "immutable",
643 Import: "import",
644 Indexed: "indexed",
645 Interface: "interface",
646 Internal: "internal",
647 Is: "is",
648 Library: "library",
649 Mapping: "mapping",
650 Memory: "memory",
651 Modifier: "modifier",
652 New: "new",
653 Override: "override",
654 Payable: "payable",
655 Pragma: "pragma",
656 Private: "private",
657 Public: "public",
658 Pure: "pure",
659 Receive: "receive",
660 Return: "return",
661 Returns: "returns",
662 Storage: "storage",
663 Struct: "struct",
664 Throw: "throw",
665 Try: "try",
666 Type: "type",
667 Unchecked: "unchecked",
668 Unicode: "unicode",
669 Using: "using",
670 View: "view",
671 Virtual: "virtual",
672 While: "while",
673
674 Int: "int",
676 Int8: "int8",
677 Int16: "int16",
678 Int24: "int24",
679 Int32: "int32",
680 Int40: "int40",
681 Int48: "int48",
682 Int56: "int56",
683 Int64: "int64",
684 Int72: "int72",
685 Int80: "int80",
686 Int88: "int88",
687 Int96: "int96",
688 Int104: "int104",
689 Int112: "int112",
690 Int120: "int120",
691 Int128: "int128",
692 Int136: "int136",
693 Int144: "int144",
694 Int152: "int152",
695 Int160: "int160",
696 Int168: "int168",
697 Int176: "int176",
698 Int184: "int184",
699 Int192: "int192",
700 Int200: "int200",
701 Int208: "int208",
702 Int216: "int216",
703 Int224: "int224",
704 Int232: "int232",
705 Int240: "int240",
706 Int248: "int248",
707 Int256: "int256",
708 UInt: "uint",
709 UInt8: "uint8",
710 UInt16: "uint16",
711 UInt24: "uint24",
712 UInt32: "uint32",
713 UInt40: "uint40",
714 UInt48: "uint48",
715 UInt56: "uint56",
716 UInt64: "uint64",
717 UInt72: "uint72",
718 UInt80: "uint80",
719 UInt88: "uint88",
720 UInt96: "uint96",
721 UInt104: "uint104",
722 UInt112: "uint112",
723 UInt120: "uint120",
724 UInt128: "uint128",
725 UInt136: "uint136",
726 UInt144: "uint144",
727 UInt152: "uint152",
728 UInt160: "uint160",
729 UInt168: "uint168",
730 UInt176: "uint176",
731 UInt184: "uint184",
732 UInt192: "uint192",
733 UInt200: "uint200",
734 UInt208: "uint208",
735 UInt216: "uint216",
736 UInt224: "uint224",
737 UInt232: "uint232",
738 UInt240: "uint240",
739 UInt248: "uint248",
740 UInt256: "uint256",
741 Bytes: "bytes",
742 Bytes1: "bytes1",
743 Bytes2: "bytes2",
744 Bytes3: "bytes3",
745 Bytes4: "bytes4",
746 Bytes5: "bytes5",
747 Bytes6: "bytes6",
748 Bytes7: "bytes7",
749 Bytes8: "bytes8",
750 Bytes9: "bytes9",
751 Bytes10: "bytes10",
752 Bytes11: "bytes11",
753 Bytes12: "bytes12",
754 Bytes13: "bytes13",
755 Bytes14: "bytes14",
756 Bytes15: "bytes15",
757 Bytes16: "bytes16",
758 Bytes17: "bytes17",
759 Bytes18: "bytes18",
760 Bytes19: "bytes19",
761 Bytes20: "bytes20",
762 Bytes21: "bytes21",
763 Bytes22: "bytes22",
764 Bytes23: "bytes23",
765 Bytes24: "bytes24",
766 Bytes25: "bytes25",
767 Bytes26: "bytes26",
768 Bytes27: "bytes27",
769 Bytes28: "bytes28",
770 Bytes29: "bytes29",
771 Bytes30: "bytes30",
772 Bytes31: "bytes31",
773 Bytes32: "bytes32",
774 String: "string",
775 Address: "address",
776 Bool: "bool",
777 Fixed: "fixed",
778 UFixed: "ufixed",
779
780 Wei: "wei",
782 Gwei: "gwei",
783 Ether: "ether",
784 Seconds: "seconds",
785 Minutes: "minutes",
786 Hours: "hours",
787 Days: "days",
788 Weeks: "weeks",
789 Years: "years",
790
791 False: "false",
793 True: "true",
794
795 After: "after",
797 Alias: "alias",
798 Apply: "apply",
799 Auto: "auto",
800 Byte: "byte",
801 Case: "case",
802 CopyOf: "copyof",
803 Default: "default",
804 Define: "define",
805 Final: "final",
806 Implements: "implements",
807 In: "in",
808 Inline: "inline",
809 Let: "let",
810 Macro: "macro",
811 Match: "match",
812 Mutable: "mutable",
813 NullLiteral: "null",
814 Of: "of",
815 Partial: "partial",
816 Promise: "promise",
817 Reference: "reference",
818 Relocatable: "relocatable",
819 Sealed: "sealed",
820 Sizeof: "sizeof",
821 Static: "static",
822 Supports: "supports",
823 Switch: "switch",
824 Typedef: "typedef",
825 TypeOf: "typeof",
826 Var: "var",
827
828 Leave: "leave",
833 Revert: "revert",
834
835 Add: "add",
840 Addmod: "addmod",
841 And: "and",
842 Balance: "balance",
843 Basefee: "basefee",
844 Blobbasefee: "blobbasefee",
845 Blobhash: "blobhash",
846 Blockhash: "blockhash",
847 Call: "call",
848 Callcode: "callcode",
849 Calldatacopy: "calldatacopy",
850 Calldataload: "calldataload",
851 Calldatasize: "calldatasize",
852 Caller: "caller",
853 Callvalue: "callvalue",
854 Chainid: "chainid",
855 Codecopy: "codecopy",
856 Codesize: "codesize",
857 Coinbase: "coinbase",
858 Create: "create",
859 Create2: "create2",
860 Delegatecall: "delegatecall",
861 Difficulty: "difficulty",
862 Div: "div",
863 Eq: "eq",
864 Exp: "exp",
865 Extcodecopy: "extcodecopy",
866 Extcodehash: "extcodehash",
867 Extcodesize: "extcodesize",
868 Gas: "gas",
869 Gaslimit: "gaslimit",
870 Gasprice: "gasprice",
871 Gt: "gt",
872 Invalid: "invalid",
873 Iszero: "iszero",
874 Keccak256: "keccak256",
875 Log0: "log0",
876 Log1: "log1",
877 Log2: "log2",
878 Log3: "log3",
879 Log4: "log4",
880 Lt: "lt",
881 Mcopy: "mcopy",
882 Mload: "mload",
883 Mod: "mod",
884 Msize: "msize",
885 Mstore: "mstore",
886 Mstore8: "mstore8",
887 Mul: "mul",
888 Mulmod: "mulmod",
889 Not: "not",
890 Number: "number",
891 Or: "or",
892 Origin: "origin",
893 Pop: "pop",
894 Prevrandao: "prevrandao",
895 Returndatacopy: "returndatacopy",
896 Returndatasize: "returndatasize",
897 Sar: "sar",
898 Sdiv: "sdiv",
899 Selfbalance: "selfbalance",
900 Selfdestruct: "selfdestruct",
901 Sgt: "sgt",
902 Shl: "shl",
903 Shr: "shr",
904 Signextend: "signextend",
905 Sload: "sload",
906 Slt: "slt",
907 Smod: "smod",
908 Sstore: "sstore",
909 Staticcall: "staticcall",
910 Stop: "stop",
911 Sub: "sub",
912 Timestamp: "timestamp",
913 Tload: "tload",
914 Tstore: "tstore",
915 Xor: "xor",
916
917 Auxdataloadn: "auxdataloadn",
918 Clz: "clz",
919 Datacopy: "datacopy",
920 Dataoffset: "dataoffset",
921 Datasize: "datasize",
922 Eofcreate: "eofcreate",
923 Extcall: "extcall",
924 Extdelegatecall: "extdelegatecall",
925 Extstaticcall: "extstaticcall",
926 Linkersymbol: "linkersymbol",
927 Loadimmutable: "loadimmutable",
928 Memoryguard: "memoryguard",
929 Returncontract: "returncontract",
930 Setimmutable: "setimmutable",
931
932 Class: "class",
934 Instantiation: "instantiation",
935 Integer: "Integer",
936 Itself: "itself",
937 StaticAssert: "static_assert",
938 Builtin: "__builtin",
939 ForAll: "forall",
940 }
941
942 Symbols {
961 Test,
962 X,
963 __tmp_struct,
964 _anonymous,
965 _recursive_internal,
966 abi,
967 abicoder,
968 assert,
969 at,
970 block,
971 code,
972 codehash,
973 concat,
974 creationCode,
975 data,
976 decode,
977 display_test,
978 ecrecover,
979 encode,
980 encodeCall,
981 encodePacked,
982 encodeWithSelector,
983 encodeWithSignature,
984 erc7201,
985 error,
986 experimental,
987 from,
988 gasleft,
989 global,
990 interfaceId,
991 layout,
992 length,
993 max,
994 memory_dash_safe: "memory-safe",
995 min,
996 msg,
997 name,
998 object,
999 offset,
1000 push,
1001 require,
1002 ripemd160,
1003 runtimeCode,
1004 salt,
1005 selector,
1006 send,
1007 sender,
1008 sha256,
1009 sig,
1010 slot,
1011 solidity,
1012 super_: "super",
1013 this,
1014 transfer,
1015 transient,
1016 tx,
1017 types,
1018 underscore: "_",
1019 unwrap,
1020 value,
1021 wrap,
1022 x,
1023 }
1024}
1025
1026#[cfg(test)]
1027mod tests {
1028 use super::*;
1029
1030 #[test]
1031 fn interner_tests() {
1032 let i = Interner::prefill(&[]);
1033 assert_eq!(i.intern("dog"), Symbol::new(0));
1035 assert_eq!(i.intern("dog"), Symbol::new(0));
1037 assert_eq!(i.intern("cat"), Symbol::new(1));
1039 assert_eq!(i.intern("cat"), Symbol::new(1));
1040 assert_eq!(i.intern("dog"), Symbol::new(0));
1042 }
1043
1044 #[test]
1045 fn defaults() {
1046 assert_eq!(Symbol::DUMMY, Symbol::new(0));
1047 assert_eq!(Symbol::DUMMY, Symbol::default());
1048 assert_eq!(Ident::DUMMY, Ident::new(Symbol::DUMMY, Span::DUMMY));
1049 assert_eq!(Ident::DUMMY, Ident::default());
1050
1051 crate::enter(|| {
1052 assert_eq!(Symbol::DUMMY.as_str(), "");
1053 assert_eq!(Symbol::DUMMY.to_string(), "");
1054 assert_eq!(Ident::DUMMY.as_str(), "");
1055 assert_eq!(Ident::DUMMY.to_string(), "");
1056 });
1057 }
1058}