]> git.lizzy.rs Git - rust.git/blob - src/libsyntax_pos/symbol.rs
Avoid unnecessary internings.
[rust.git] / src / libsyntax_pos / symbol.rs
1 //! An "interner" is a data structure that associates values with usize tags and
2 //! allows bidirectional lookup; i.e., given a value, one can easily find the
3 //! type, and vice versa.
4
5 use arena::DroplessArena;
6 use rustc_data_structures::fx::FxHashMap;
7 use rustc_data_structures::indexed_vec::Idx;
8 use rustc_data_structures::newtype_index;
9 use rustc_macros::symbols;
10 use serialize::{Decodable, Decoder, Encodable, Encoder};
11
12 use std::fmt;
13 use std::str;
14 use std::cmp::{PartialEq, Ordering, PartialOrd, Ord};
15 use std::hash::{Hash, Hasher};
16
17 use crate::hygiene::SyntaxContext;
18 use crate::{Span, DUMMY_SP, GLOBALS};
19
20 symbols! {
21     // After modifying this list adjust `is_special`, `is_used_keyword`/`is_unused_keyword`,
22     // this should be rarely necessary though if the keywords are kept in alphabetic order.
23     Keywords {
24         // Special reserved identifiers used internally for elided lifetimes,
25         // unnamed method parameters, crate root module, error recovery etc.
26         Invalid:            "",
27         PathRoot:           "{{root}}",
28         DollarCrate:        "$crate",
29         Underscore:         "_",
30
31         // Keywords that are used in stable Rust.
32         As:                 "as",
33         Break:              "break",
34         Const:              "const",
35         Continue:           "continue",
36         Crate:              "crate",
37         Else:               "else",
38         Enum:               "enum",
39         Extern:             "extern",
40         False:              "false",
41         Fn:                 "fn",
42         For:                "for",
43         If:                 "if",
44         Impl:               "impl",
45         In:                 "in",
46         Let:                "let",
47         Loop:               "loop",
48         Match:              "match",
49         Mod:                "mod",
50         Move:               "move",
51         Mut:                "mut",
52         Pub:                "pub",
53         Ref:                "ref",
54         Return:             "return",
55         SelfLower:          "self",
56         SelfUpper:          "Self",
57         Static:             "static",
58         Struct:             "struct",
59         Super:              "super",
60         Trait:              "trait",
61         True:               "true",
62         Type:               "type",
63         Unsafe:             "unsafe",
64         Use:                "use",
65         Where:              "where",
66         While:              "while",
67
68         // Keywords that are used in unstable Rust or reserved for future use.
69         Abstract:           "abstract",
70         Become:             "become",
71         Box:                "box",
72         Do:                 "do",
73         Final:              "final",
74         Macro:              "macro",
75         Override:           "override",
76         Priv:               "priv",
77         Typeof:             "typeof",
78         Unsized:            "unsized",
79         Virtual:            "virtual",
80         Yield:              "yield",
81
82         // Edition-specific keywords that are used in stable Rust.
83         Dyn:                "dyn", // >= 2018 Edition only
84
85         // Edition-specific keywords that are used in unstable Rust or reserved for future use.
86         Async:              "async", // >= 2018 Edition only
87         Await:              "await", // >= 2018 Edition only
88         Try:                "try", // >= 2018 Edition only
89
90         // Special lifetime names
91         UnderscoreLifetime: "'_",
92         StaticLifetime:     "'static",
93
94         // Weak keywords, have special meaning only in specific contexts.
95         Auto:               "auto",
96         Catch:              "catch",
97         Default:            "default",
98         Existential:        "existential",
99         Union:              "union",
100     }
101
102     // Symbols that can be referred to with syntax_pos::sym::*. The symbol is
103     // the stringified identifier unless otherwise specified (e.g.
104     // `proc_dash_macro` represents "proc-macro").
105     Symbols {
106         aarch64_target_feature,
107         abi,
108         abi_amdgpu_kernel,
109         abi_msp430_interrupt,
110         abi_ptx,
111         abi_sysv64,
112         abi_thiscall,
113         abi_unadjusted,
114         abi_vectorcall,
115         abi_x86_interrupt,
116         aborts,
117         advanced_slice_patterns,
118         adx_target_feature,
119         alias,
120         align,
121         alignstack,
122         all,
123         allocator,
124         allocator_internals,
125         alloc_error_handler,
126         allow,
127         allowed,
128         allow_fail,
129         allow_internal_unsafe,
130         allow_internal_unstable,
131         allow_internal_unstable_backcompat_hack,
132         always,
133         any,
134         arbitrary_self_types,
135         arm_target_feature,
136         asm,
137         associated_consts,
138         associated_type_defaults,
139         associated_types,
140         async_await,
141         attr,
142         attributes,
143         attr_literals,
144         augmented_assignments,
145         automatically_derived,
146         avx512_target_feature,
147         await_macro,
148         bench,
149         bin,
150         bind_by_move_pattern_guards,
151         block,
152         borrowck_graphviz_postflow,
153         borrowck_graphviz_preflow,
154         box_patterns,
155         box_syntax,
156         braced_empty_structs,
157         C,
158         cdylib,
159         cfg,
160         cfg_attr,
161         cfg_attr_multi,
162         cfg_target_feature,
163         cfg_target_has_atomic,
164         cfg_target_thread_local,
165         cfg_target_vendor,
166         clone,
167         clone_closures,
168         clone_from,
169         closure_to_fn_coercion,
170         cmpxchg16b_target_feature,
171         cold,
172         compile_error,
173         compiler_builtins,
174         concat_idents,
175         conservative_impl_trait,
176         console,
177         const_compare_raw_pointers,
178         const_fn,
179         const_fn_union,
180         const_generics,
181         const_indexing,
182         const_let,
183         const_panic,
184         const_raw_ptr_deref,
185         const_raw_ptr_to_usize_cast,
186         const_transmute,
187         contents,
188         convert,
189         copy_closures,
190         core,
191         core_intrinsics,
192         crate_id,
193         crate_in_paths,
194         crate_name,
195         crate_type,
196         crate_visibility_modifier,
197         custom_attribute,
198         custom_derive,
199         custom_inner_attributes,
200         custom_test_frameworks,
201         c_variadic,
202         decl_macro,
203         default_lib_allocator,
204         default_type_parameter_fallback,
205         default_type_params,
206         deny,
207         deprecated,
208         deref,
209         deref_mut,
210         derive,
211         doc,
212         doc_alias,
213         doc_cfg,
214         doc_keyword,
215         doc_masked,
216         doc_spotlight,
217         document_private_items,
218         dotdoteq_in_patterns,
219         dotdot_in_tuple_patterns,
220         double_braced_crate: "{{crate}}",
221         double_braced_impl: "{{impl}}",
222         double_braced_misc: "{{misc}}",
223         double_braced_closure: "{{closure}}",
224         double_braced_constructor: "{{constructor}}",
225         double_braced_constant: "{{constant}}",
226         double_braced_opaque: "{{opaque}}",
227         dropck_eyepatch,
228         dropck_parametricity,
229         drop_types_in_const,
230         dylib,
231         dyn_trait,
232         eh_personality,
233         eh_unwind_resume,
234         enable,
235         err,
236         Err,
237         except,
238         exclusive_range_pattern,
239         exhaustive_integer_patterns,
240         exhaustive_patterns,
241         existential_type,
242         expected,
243         export_name,
244         extern_absolute_paths,
245         external_doc,
246         extern_crate_item_prelude,
247         extern_crate_self,
248         extern_in_paths,
249         extern_prelude,
250         extern_types,
251         f16c_target_feature,
252         f32,
253         f64,
254         feature,
255         ffi_returns_twice,
256         field,
257         field_init_shorthand,
258         file,
259         fmt_internals,
260         fn_must_use,
261         forbid,
262         format_args_nl,
263         from,
264         From,
265         from_error,
266         from_generator,
267         from_ok,
268         fundamental,
269         future,
270         Future,
271         gen_future,
272         generators,
273         generic_associated_types,
274         generic_param_attrs,
275         global_allocator,
276         global_asm,
277         globs,
278         hexagon_target_feature,
279         hidden,
280         homogeneous_aggregate,
281         html_favicon_url,
282         html_logo_url,
283         html_no_source,
284         html_playground_url,
285         html_root_url,
286         i128,
287         i128_type,
288         i16,
289         i32,
290         i64,
291         i8,
292         ident,
293         if_let,
294         if_while_or_patterns,
295         ignore,
296         impl_header_lifetime_elision,
297         impl_trait_in_bindings,
298         import_shadowing,
299         index,
300         index_mut,
301         in_band_lifetimes,
302         include,
303         inclusive_range_syntax,
304         infer_outlives_requirements,
305         infer_static_outlives_requirements,
306         inline,
307         intel,
308         into_iter,
309         IntoIterator,
310         into_result,
311         intrinsics,
312         irrefutable_let_patterns,
313         isize,
314         issue,
315         issue_5723_bootstrap,
316         issue_tracker_base_url,
317         item_like_imports,
318         iter,
319         Iterator,
320         keyword,
321         kind,
322         label,
323         label_break_value,
324         lang,
325         lang_items,
326         lib,
327         link,
328         linkage,
329         link_args,
330         link_cfg,
331         link_llvm_intrinsics,
332         link_name,
333         link_section,
334         lint_reasons,
335         local_inner_macros,
336         log_syntax,
337         loop_break_value,
338         macro_at_most_once_rep,
339         macro_escape,
340         macro_export,
341         macro_lifetime_matcher,
342         macro_literal_matcher,
343         macro_reexport,
344         macro_rules,
345         macros_in_extern,
346         macro_use,
347         macro_vis_matcher,
348         main,
349         managed_boxes,
350         marker,
351         marker_trait_attr,
352         masked,
353         match_beginning_vert,
354         match_default_bindings,
355         may_dangle,
356         message,
357         meta,
358         min_const_fn,
359         min_const_unsafe_fn,
360         mips_target_feature,
361         mmx_target_feature,
362         module,
363         more_struct_aliases,
364         movbe_target_feature,
365         must_use,
366         naked,
367         naked_functions,
368         name,
369         needs_allocator,
370         needs_panic_runtime,
371         negate_unsigned,
372         never,
373         never_type,
374         next,
375         __next,
376         nll,
377         no_builtins,
378         no_core,
379         no_crate_inject,
380         no_debug,
381         no_default_passes,
382         no_implicit_prelude,
383         no_inline,
384         no_link,
385         no_main,
386         no_mangle,
387         non_ascii_idents,
388         None,
389         non_exhaustive,
390         non_modrs_mods,
391         no_stack_check,
392         no_start,
393         no_std,
394         not,
395         note,
396         Ok,
397         omit_gdb_pretty_printer_section,
398         on,
399         on_unimplemented,
400         oom,
401         ops,
402         optimize,
403         optimize_attribute,
404         optin_builtin_traits,
405         option,
406         Option,
407         opt_out_copy,
408         Output,
409         overlapping_marker_traits,
410         packed,
411         panic,
412         panic_handler,
413         panic_impl,
414         panic_implementation,
415         panic_runtime,
416         passes,
417         path,
418         pattern_parentheses,
419         Pending,
420         pin,
421         Pin,
422         pinned,
423         platform_intrinsics,
424         plugin,
425         plugin_registrar,
426         plugins,
427         Poll,
428         poll_with_tls_context,
429         powerpc_target_feature,
430         precise_pointer_size_matching,
431         prelude,
432         prelude_import,
433         primitive,
434         proc_dash_macro: "proc-macro",
435         proc_macro,
436         proc_macro_attribute,
437         proc_macro_def_site,
438         proc_macro_derive,
439         proc_macro_expr,
440         proc_macro_gen,
441         proc_macro_hygiene,
442         proc_macro_mod,
443         proc_macro_non_items,
444         proc_macro_path_invoc,
445         profiler_runtime,
446         pub_restricted,
447         pushpop_unsafe,
448         quad_precision_float,
449         question_mark,
450         quote,
451         Range,
452         RangeFrom,
453         RangeFull,
454         RangeInclusive,
455         RangeTo,
456         RangeToInclusive,
457         raw_identifiers,
458         Ready,
459         reason,
460         recursion_limit,
461         reexport_test_harness_main,
462         reflect,
463         relaxed_adts,
464         repr,
465         repr128,
466         repr_align,
467         repr_align_enum,
468         repr_packed,
469         repr_simd,
470         repr_transparent,
471         re_rebalance_coherence,
472         result,
473         Result,
474         Return,
475         rlib,
476         rtm_target_feature,
477         rust,
478         rust_2015_preview,
479         rust_2018_preview,
480         rust_begin_unwind,
481         rustc_allocator_nounwind,
482         rustc_allow_const_fn_ptr,
483         rustc_args_required_const,
484         rustc_attrs,
485         rustc_clean,
486         rustc_const_unstable,
487         rustc_conversion_suggestion,
488         rustc_copy_clone_marker,
489         rustc_def_path,
490         rustc_deprecated,
491         rustc_diagnostic_macros,
492         rustc_dirty,
493         rustc_doc_only_macro,
494         rustc_dump_env_program_clauses,
495         rustc_dump_program_clauses,
496         rustc_dump_user_substs,
497         rustc_error,
498         rustc_expected_cgu_reuse,
499         rustc_if_this_changed,
500         rustc_inherit_overflow_checks,
501         rustc_layout,
502         rustc_layout_scalar_valid_range_end,
503         rustc_layout_scalar_valid_range_start,
504         rustc_mir,
505         rustc_nonnull_optimization_guaranteed,
506         rustc_object_lifetime_default,
507         rustc_on_unimplemented,
508         rustc_outlives,
509         rustc_paren_sugar,
510         rustc_partition_codegened,
511         rustc_partition_reused,
512         rustc_peek,
513         rustc_peek_definite_init,
514         rustc_peek_maybe_init,
515         rustc_peek_maybe_uninit,
516         rustc_private,
517         rustc_proc_macro_decls,
518         rustc_promotable,
519         rustc_regions,
520         rustc_stable,
521         rustc_std_internal_symbol,
522         rustc_symbol_name,
523         rustc_synthetic,
524         rustc_test_marker,
525         rustc_then_this_would_need,
526         rustc_transparent_macro,
527         rustc_variance,
528         rustdoc,
529         rust_eh_personality,
530         rust_eh_unwind_resume,
531         rust_oom,
532         __rust_unstable_column,
533         rvalue_static_promotion,
534         sanitizer_runtime,
535         self_in_typedefs,
536         self_struct_ctor,
537         Send,
538         should_panic,
539         simd,
540         simd_ffi,
541         since,
542         size,
543         slice_patterns,
544         slicing_syntax,
545         Some,
546         specialization,
547         speed,
548         spotlight,
549         sse4a_target_feature,
550         stable,
551         staged_api,
552         start,
553         static_in_const,
554         staticlib,
555         static_nobundle,
556         static_recursion,
557         std,
558         str,
559         stmt_expr_attributes,
560         stop_after_dataflow,
561         struct_field_attributes,
562         struct_inherit,
563         structural_match,
564         struct_variant,
565         suggestion,
566         target_feature,
567         target_has_atomic,
568         target_thread_local,
569         task,
570         tbm_target_feature,
571         termination_trait,
572         termination_trait_test,
573         test,
574         test_2018_feature,
575         test_accepted_feature,
576         test_case,
577         test_removed_feature,
578         test_runner,
579         thread_local,
580         tool_attributes,
581         tool_lints,
582         trace_macros,
583         trait_alias,
584         transmute,
585         transparent,
586         trivial_bounds,
587         Try,
588         try_blocks,
589         try_trait,
590         tuple_indexing,
591         ty,
592         type_alias_enum_variants,
593         type_ascription,
594         type_length_limit,
595         type_macros,
596         u128,
597         u16,
598         u32,
599         u64,
600         u8,
601         unboxed_closures,
602         underscore_const_names,
603         underscore_imports,
604         underscore_lifetimes,
605         uniform_paths,
606         universal_impl_trait,
607         unmarked_api,
608         unreachable_code,
609         unrestricted_attribute_tokens,
610         unsafe_destructor_blind_to_params,
611         unsafe_no_drop_flag,
612         unsized_locals,
613         unsized_tuple_coercion,
614         unstable,
615         untagged_unions,
616         unwind,
617         unwind_attributes,
618         used,
619         use_extern_macros,
620         use_nested_groups,
621         usize,
622         v1,
623         val,
624         vis,
625         visible_private_types,
626         volatile,
627         warn,
628         warn_directory_ownership,
629         wasm_import_module,
630         wasm_target_feature,
631         while_let,
632         windows,
633         windows_subsystem,
634         Yield,
635     }
636 }
637
638 #[derive(Copy, Clone, Eq)]
639 pub struct Ident {
640     pub name: Symbol,
641     pub span: Span,
642 }
643
644 impl Ident {
645     #[inline]
646     /// Constructs a new identifier from a symbol and a span.
647     pub const fn new(name: Symbol, span: Span) -> Ident {
648         Ident { name, span }
649     }
650
651     /// Constructs a new identifier with an empty syntax context.
652     #[inline]
653     pub const fn with_empty_ctxt(name: Symbol) -> Ident {
654         Ident::new(name, DUMMY_SP)
655     }
656
657     #[inline]
658     pub fn invalid() -> Ident {
659         Ident::with_empty_ctxt(kw::Invalid)
660     }
661
662     /// Maps an interned string to an identifier with an empty syntax context.
663     pub fn from_interned_str(string: InternedString) -> Ident {
664         Ident::with_empty_ctxt(string.as_symbol())
665     }
666
667     /// Maps a string to an identifier with an empty span.
668     pub fn from_str(string: &str) -> Ident {
669         Ident::with_empty_ctxt(Symbol::intern(string))
670     }
671
672     /// Maps a string and a span to an identifier.
673     pub fn from_str_and_span(string: &str, span: Span) -> Ident {
674         Ident::new(Symbol::intern(string), span)
675     }
676
677     /// Replaces `lo` and `hi` with those from `span`, but keep hygiene context.
678     pub fn with_span_pos(self, span: Span) -> Ident {
679         Ident::new(self.name, span.with_ctxt(self.span.ctxt()))
680     }
681
682     pub fn without_first_quote(self) -> Ident {
683         Ident::new(Symbol::intern(self.as_str().trim_start_matches('\'')), self.span)
684     }
685
686     /// "Normalize" ident for use in comparisons using "item hygiene".
687     /// Identifiers with same string value become same if they came from the same "modern" macro
688     /// (e.g., `macro` item, but not `macro_rules` item) and stay different if they came from
689     /// different "modern" macros.
690     /// Technically, this operation strips all non-opaque marks from ident's syntactic context.
691     pub fn modern(self) -> Ident {
692         Ident::new(self.name, self.span.modern())
693     }
694
695     /// "Normalize" ident for use in comparisons using "local variable hygiene".
696     /// Identifiers with same string value become same if they came from the same non-transparent
697     /// macro (e.g., `macro` or `macro_rules!` items) and stay different if they came from different
698     /// non-transparent macros.
699     /// Technically, this operation strips all transparent marks from ident's syntactic context.
700     pub fn modern_and_legacy(self) -> Ident {
701         Ident::new(self.name, self.span.modern_and_legacy())
702     }
703
704     /// Transforms an identifier into one with the same name, but gensymed.
705     pub fn gensym(self) -> Ident {
706         let name = with_interner(|interner| interner.gensymed(self.name));
707         Ident::new(name, self.span)
708     }
709
710     /// Transforms an underscore identifier into one with the same name, but
711     /// gensymed. Leaves non-underscore identifiers unchanged.
712     pub fn gensym_if_underscore(self) -> Ident {
713         if self.name == kw::Underscore { self.gensym() } else { self }
714     }
715
716     // WARNING: this function is deprecated and will be removed in the future.
717     pub fn is_gensymed(self) -> bool {
718         with_interner(|interner| interner.is_gensymed(self.name))
719     }
720
721     pub fn as_str(self) -> LocalInternedString {
722         self.name.as_str()
723     }
724
725     pub fn as_interned_str(self) -> InternedString {
726         self.name.as_interned_str()
727     }
728 }
729
730 impl PartialEq for Ident {
731     fn eq(&self, rhs: &Self) -> bool {
732         self.name == rhs.name && self.span.ctxt() == rhs.span.ctxt()
733     }
734 }
735
736 impl Hash for Ident {
737     fn hash<H: Hasher>(&self, state: &mut H) {
738         self.name.hash(state);
739         self.span.ctxt().hash(state);
740     }
741 }
742
743 impl fmt::Debug for Ident {
744     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
745         write!(f, "{}{:?}", self.name, self.span.ctxt())
746     }
747 }
748
749 impl fmt::Display for Ident {
750     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
751         fmt::Display::fmt(&self.name, f)
752     }
753 }
754
755 impl Encodable for Ident {
756     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
757         if self.span.ctxt().modern() == SyntaxContext::empty() {
758             s.emit_str(&self.as_str())
759         } else { // FIXME(jseyfried): intercrate hygiene
760             let mut string = "#".to_owned();
761             string.push_str(&self.as_str());
762             s.emit_str(&string)
763         }
764     }
765 }
766
767 impl Decodable for Ident {
768     fn decode<D: Decoder>(d: &mut D) -> Result<Ident, D::Error> {
769         let string = d.read_str()?;
770         Ok(if !string.starts_with('#') {
771             Ident::from_str(&string)
772         } else { // FIXME(jseyfried): intercrate hygiene
773             Ident::from_str(&string[1..]).gensym()
774         })
775     }
776 }
777
778 /// A symbol is an interned or gensymed string. A gensym is a symbol that is
779 /// never equal to any other symbol.
780 ///
781 /// Conceptually, a gensym can be thought of as a normal symbol with an
782 /// invisible unique suffix. Gensyms are useful when creating new identifiers
783 /// that must not match any existing identifiers, e.g. during macro expansion
784 /// and syntax desugaring. Because gensyms should always be identifiers, all
785 /// gensym operations are on `Ident` rather than `Symbol`. (Indeed, in the
786 /// future the gensym-ness may be moved from `Symbol` to hygiene data.)
787 ///
788 /// Examples:
789 /// ```
790 /// assert_eq!(Ident::from_str("x"), Ident::from_str("x"))
791 /// assert_ne!(Ident::from_str("x").gensym(), Ident::from_str("x"))
792 /// assert_ne!(Ident::from_str("x").gensym(), Ident::from_str("x").gensym())
793 /// ```
794 /// Internally, a symbol is implemented as an index, and all operations
795 /// (including hashing, equality, and ordering) operate on that index. The use
796 /// of `newtype_index!` means that `Option<Symbol>` only takes up 4 bytes,
797 /// because `newtype_index!` reserves the last 256 values for tagging purposes.
798 ///
799 /// Note that `Symbol` cannot directly be a `newtype_index!` because it
800 /// implements `fmt::Debug`, `Encodable`, and `Decodable` in special ways.
801 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
802 pub struct Symbol(SymbolIndex);
803
804 newtype_index! {
805     pub struct SymbolIndex { .. }
806 }
807
808 impl Symbol {
809     const fn new(n: u32) -> Self {
810         Symbol(SymbolIndex::from_u32_const(n))
811     }
812
813     /// Maps a string to its interned representation.
814     pub fn intern(string: &str) -> Self {
815         with_interner(|interner| interner.intern(string))
816     }
817
818     pub fn as_str(self) -> LocalInternedString {
819         with_interner(|interner| unsafe {
820             LocalInternedString {
821                 string: std::mem::transmute::<&str, &str>(interner.get(self))
822             }
823         })
824     }
825
826     pub fn as_interned_str(self) -> InternedString {
827         with_interner(|interner| InternedString {
828             symbol: interner.interned(self)
829         })
830     }
831
832     pub fn as_u32(self) -> u32 {
833         self.0.as_u32()
834     }
835 }
836
837 impl fmt::Debug for Symbol {
838     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
839         let is_gensymed = with_interner(|interner| interner.is_gensymed(*self));
840         if is_gensymed {
841             write!(f, "{}({:?})", self, self.0)
842         } else {
843             write!(f, "{}", self)
844         }
845     }
846 }
847
848 impl fmt::Display for Symbol {
849     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
850         fmt::Display::fmt(&self.as_str(), f)
851     }
852 }
853
854 impl Encodable for Symbol {
855     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
856         s.emit_str(&self.as_str())
857     }
858 }
859
860 impl Decodable for Symbol {
861     fn decode<D: Decoder>(d: &mut D) -> Result<Symbol, D::Error> {
862         Ok(Symbol::intern(&d.read_str()?))
863     }
864 }
865
866 // The `&'static str`s in this type actually point into the arena.
867 //
868 // Note that normal symbols are indexed upward from 0, and gensyms are indexed
869 // downward from SymbolIndex::MAX_AS_U32.
870 #[derive(Default)]
871 pub struct Interner {
872     arena: DroplessArena,
873     names: FxHashMap<&'static str, Symbol>,
874     strings: Vec<&'static str>,
875     gensyms: Vec<Symbol>,
876 }
877
878 impl Interner {
879     fn prefill(init: &[&'static str]) -> Self {
880         let symbols = (0 .. init.len() as u32).map(Symbol::new);
881         Interner {
882             strings: init.to_vec(),
883             names: init.iter().copied().zip(symbols).collect(),
884             ..Default::default()
885         }
886     }
887
888     pub fn intern(&mut self, string: &str) -> Symbol {
889         if let Some(&name) = self.names.get(string) {
890             return name;
891         }
892
893         let name = Symbol::new(self.strings.len() as u32);
894
895         // `from_utf8_unchecked` is safe since we just allocated a `&str` which is known to be
896         // UTF-8.
897         let string: &str = unsafe {
898             str::from_utf8_unchecked(self.arena.alloc_slice(string.as_bytes()))
899         };
900         // It is safe to extend the arena allocation to `'static` because we only access
901         // these while the arena is still alive.
902         let string: &'static str =  unsafe {
903             &*(string as *const str)
904         };
905         self.strings.push(string);
906         self.names.insert(string, name);
907         name
908     }
909
910     fn interned(&self, symbol: Symbol) -> Symbol {
911         if (symbol.0.as_usize()) < self.strings.len() {
912             symbol
913         } else {
914             self.gensyms[(SymbolIndex::MAX_AS_U32 - symbol.0.as_u32()) as usize]
915         }
916     }
917
918     fn gensymed(&mut self, symbol: Symbol) -> Symbol {
919         self.gensyms.push(symbol);
920         Symbol::new(SymbolIndex::MAX_AS_U32 - self.gensyms.len() as u32 + 1)
921     }
922
923     fn is_gensymed(&mut self, symbol: Symbol) -> bool {
924         symbol.0.as_usize() >= self.strings.len()
925     }
926
927     // Get the symbol as a string. `Symbol::as_str()` should be used in
928     // preference to this function.
929     pub fn get(&self, symbol: Symbol) -> &str {
930         match self.strings.get(symbol.0.as_usize()) {
931             Some(string) => string,
932             None => {
933                 let symbol = self.gensyms[(SymbolIndex::MAX_AS_U32 - symbol.0.as_u32()) as usize];
934                 self.strings[symbol.0.as_usize()]
935             }
936         }
937     }
938 }
939
940 // This module has a very short name because it's used a lot.
941 pub mod kw {
942     use super::Symbol;
943     keywords!();
944 }
945
946 // This module has a very short name because it's used a lot.
947 pub mod sym {
948     use super::Symbol;
949     symbols!();
950 }
951
952 impl Symbol {
953     fn is_used_keyword_2018(self) -> bool {
954         self == kw::Dyn
955     }
956
957     fn is_unused_keyword_2018(self) -> bool {
958         self >= kw::Async && self <= kw::Try
959     }
960
961     /// Used for sanity checking rustdoc keyword sections.
962     pub fn is_doc_keyword(self) -> bool {
963         self <= kw::Union
964     }
965 }
966
967 impl Ident {
968     // Returns `true` for reserved identifiers used internally for elided lifetimes,
969     // unnamed method parameters, crate root module, error recovery etc.
970     pub fn is_special(self) -> bool {
971         self.name <= kw::Underscore
972     }
973
974     /// Returns `true` if the token is a keyword used in the language.
975     pub fn is_used_keyword(self) -> bool {
976         // Note: `span.edition()` is relatively expensive, don't call it unless necessary.
977         self.name >= kw::As && self.name <= kw::While ||
978         self.name.is_used_keyword_2018() && self.span.rust_2018()
979     }
980
981     /// Returns `true` if the token is a keyword reserved for possible future use.
982     pub fn is_unused_keyword(self) -> bool {
983         // Note: `span.edition()` is relatively expensive, don't call it unless necessary.
984         self.name >= kw::Abstract && self.name <= kw::Yield ||
985         self.name.is_unused_keyword_2018() && self.span.rust_2018()
986     }
987
988     /// Returns `true` if the token is either a special identifier or a keyword.
989     pub fn is_reserved(self) -> bool {
990         self.is_special() || self.is_used_keyword() || self.is_unused_keyword()
991     }
992
993     /// A keyword or reserved identifier that can be used as a path segment.
994     pub fn is_path_segment_keyword(self) -> bool {
995         self.name == kw::Super ||
996         self.name == kw::SelfLower ||
997         self.name == kw::SelfUpper ||
998         self.name == kw::Crate ||
999         self.name == kw::PathRoot ||
1000         self.name == kw::DollarCrate
1001     }
1002
1003     /// This identifier can be a raw identifier.
1004     pub fn can_be_raw(self) -> bool {
1005         self.name != kw::Invalid && self.name != kw::Underscore &&
1006         !self.is_path_segment_keyword()
1007     }
1008
1009     /// We see this identifier in a normal identifier position, like variable name or a type.
1010     /// How was it written originally? Did it use the raw form? Let's try to guess.
1011     pub fn is_raw_guess(self) -> bool {
1012         self.can_be_raw() && self.is_reserved()
1013     }
1014 }
1015
1016 // If an interner exists, return it. Otherwise, prepare a fresh one.
1017 #[inline]
1018 fn with_interner<T, F: FnOnce(&mut Interner) -> T>(f: F) -> T {
1019     GLOBALS.with(|globals| f(&mut *globals.symbol_interner.lock()))
1020 }
1021
1022 /// An alternative to `Symbol` and `InternedString`, useful when the chars
1023 /// within the symbol need to be accessed. It is best used for temporary
1024 /// values.
1025 ///
1026 /// Because the interner outlives any thread which uses this type, we can
1027 /// safely treat `string` which points to interner data, as an immortal string,
1028 /// as long as this type never crosses between threads.
1029 //
1030 // FIXME: ensure that the interner outlives any thread which uses
1031 // `LocalInternedString`, by creating a new thread right after constructing the
1032 // interner.
1033 #[derive(Clone, Copy, Hash, PartialOrd, Eq, Ord)]
1034 pub struct LocalInternedString {
1035     string: &'static str,
1036 }
1037
1038 impl LocalInternedString {
1039     /// Maps a string to its interned representation.
1040     pub fn intern(string: &str) -> Self {
1041         let string = with_interner(|interner| {
1042             let symbol = interner.intern(string);
1043             interner.strings[symbol.0.as_usize()]
1044         });
1045         LocalInternedString {
1046             string: unsafe { std::mem::transmute::<&str, &str>(string) }
1047         }
1048     }
1049
1050     pub fn as_interned_str(self) -> InternedString {
1051         InternedString {
1052             symbol: Symbol::intern(self.string)
1053         }
1054     }
1055
1056     pub fn get(&self) -> &str {
1057         // This returns a valid string since we ensure that `self` outlives the interner
1058         // by creating the interner on a thread which outlives threads which can access it.
1059         // This type cannot move to a thread which outlives the interner since it does
1060         // not implement Send.
1061         self.string
1062     }
1063 }
1064
1065 impl<U: ?Sized> std::convert::AsRef<U> for LocalInternedString
1066 where
1067     str: std::convert::AsRef<U>
1068 {
1069     fn as_ref(&self) -> &U {
1070         self.string.as_ref()
1071     }
1072 }
1073
1074 impl<T: std::ops::Deref<Target = str>> std::cmp::PartialEq<T> for LocalInternedString {
1075     fn eq(&self, other: &T) -> bool {
1076         self.string == other.deref()
1077     }
1078 }
1079
1080 impl std::cmp::PartialEq<LocalInternedString> for str {
1081     fn eq(&self, other: &LocalInternedString) -> bool {
1082         self == other.string
1083     }
1084 }
1085
1086 impl<'a> std::cmp::PartialEq<LocalInternedString> for &'a str {
1087     fn eq(&self, other: &LocalInternedString) -> bool {
1088         *self == other.string
1089     }
1090 }
1091
1092 impl std::cmp::PartialEq<LocalInternedString> for String {
1093     fn eq(&self, other: &LocalInternedString) -> bool {
1094         self == other.string
1095     }
1096 }
1097
1098 impl<'a> std::cmp::PartialEq<LocalInternedString> for &'a String {
1099     fn eq(&self, other: &LocalInternedString) -> bool {
1100         *self == other.string
1101     }
1102 }
1103
1104 impl !Send for LocalInternedString {}
1105 impl !Sync for LocalInternedString {}
1106
1107 impl std::ops::Deref for LocalInternedString {
1108     type Target = str;
1109     fn deref(&self) -> &str { self.string }
1110 }
1111
1112 impl fmt::Debug for LocalInternedString {
1113     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1114         fmt::Debug::fmt(self.string, f)
1115     }
1116 }
1117
1118 impl fmt::Display for LocalInternedString {
1119     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1120         fmt::Display::fmt(self.string, f)
1121     }
1122 }
1123
1124 impl Decodable for LocalInternedString {
1125     fn decode<D: Decoder>(d: &mut D) -> Result<LocalInternedString, D::Error> {
1126         Ok(LocalInternedString::intern(&d.read_str()?))
1127     }
1128 }
1129
1130 impl Encodable for LocalInternedString {
1131     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
1132         s.emit_str(self.string)
1133     }
1134 }
1135
1136 /// An alternative to `Symbol` that is focused on string contents. It has two
1137 /// main differences to `Symbol`.
1138 ///
1139 /// First, its implementations of `Hash`, `PartialOrd` and `Ord` work with the
1140 /// string chars rather than the symbol integer. This is useful when hash
1141 /// stability is required across compile sessions, or a guaranteed sort
1142 /// ordering is required.
1143 ///
1144 /// Second, gensym-ness is irrelevant. E.g.:
1145 /// ```
1146 /// assert_ne!(Symbol::gensym("x"), Symbol::gensym("x"))
1147 /// assert_eq!(Symbol::gensym("x").as_interned_str(), Symbol::gensym("x").as_interned_str())
1148 /// ```
1149 #[derive(Clone, Copy, PartialEq, Eq)]
1150 pub struct InternedString {
1151     symbol: Symbol,
1152 }
1153
1154 impl InternedString {
1155     /// Maps a string to its interned representation.
1156     pub fn intern(string: &str) -> Self {
1157         InternedString {
1158             symbol: Symbol::intern(string)
1159         }
1160     }
1161
1162     pub fn with<F: FnOnce(&str) -> R, R>(self, f: F) -> R {
1163         let str = with_interner(|interner| {
1164             interner.get(self.symbol) as *const str
1165         });
1166         // This is safe because the interner keeps string alive until it is dropped.
1167         // We can access it because we know the interner is still alive since we use a
1168         // scoped thread local to access it, and it was alive at the beginning of this scope
1169         unsafe { f(&*str) }
1170     }
1171
1172     fn with2<F: FnOnce(&str, &str) -> R, R>(self, other: &InternedString, f: F) -> R {
1173         let (self_str, other_str) = with_interner(|interner| {
1174             (interner.get(self.symbol) as *const str,
1175              interner.get(other.symbol) as *const str)
1176         });
1177         // This is safe for the same reason that `with` is safe.
1178         unsafe { f(&*self_str, &*other_str) }
1179     }
1180
1181     pub fn as_symbol(self) -> Symbol {
1182         self.symbol
1183     }
1184
1185     pub fn as_str(self) -> LocalInternedString {
1186         self.symbol.as_str()
1187     }
1188 }
1189
1190 impl Hash for InternedString {
1191     fn hash<H: Hasher>(&self, state: &mut H) {
1192         self.with(|str| str.hash(state))
1193     }
1194 }
1195
1196 impl PartialOrd<InternedString> for InternedString {
1197     fn partial_cmp(&self, other: &InternedString) -> Option<Ordering> {
1198         if self.symbol == other.symbol {
1199             return Some(Ordering::Equal);
1200         }
1201         self.with2(other, |self_str, other_str| self_str.partial_cmp(other_str))
1202     }
1203 }
1204
1205 impl Ord for InternedString {
1206     fn cmp(&self, other: &InternedString) -> Ordering {
1207         if self.symbol == other.symbol {
1208             return Ordering::Equal;
1209         }
1210         self.with2(other, |self_str, other_str| self_str.cmp(other_str))
1211     }
1212 }
1213
1214 impl fmt::Debug for InternedString {
1215     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1216         self.with(|str| fmt::Debug::fmt(&str, f))
1217     }
1218 }
1219
1220 impl fmt::Display for InternedString {
1221     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1222         self.with(|str| fmt::Display::fmt(&str, f))
1223     }
1224 }
1225
1226 impl Decodable for InternedString {
1227     fn decode<D: Decoder>(d: &mut D) -> Result<InternedString, D::Error> {
1228         Ok(InternedString::intern(&d.read_str()?))
1229     }
1230 }
1231
1232 impl Encodable for InternedString {
1233     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
1234         self.with(|string| s.emit_str(string))
1235     }
1236 }
1237
1238 #[cfg(test)]
1239 mod tests {
1240     use super::*;
1241     use crate::Globals;
1242     use crate::edition;
1243
1244     #[test]
1245     fn interner_tests() {
1246         let mut i: Interner = Interner::default();
1247         // first one is zero:
1248         assert_eq!(i.intern("dog"), Symbol::new(0));
1249         // re-use gets the same entry:
1250         assert_eq!(i.intern("dog"), Symbol::new(0));
1251         // different string gets a different #:
1252         assert_eq!(i.intern("cat"), Symbol::new(1));
1253         assert_eq!(i.intern("cat"), Symbol::new(1));
1254         // dog is still at zero
1255         assert_eq!(i.intern("dog"), Symbol::new(0));
1256         let z = i.intern("zebra");
1257         assert_eq!(i.gensymed(z), Symbol::new(SymbolIndex::MAX_AS_U32));
1258         // gensym of same string gets new number:
1259         assert_eq!(i.gensymed(z), Symbol::new(SymbolIndex::MAX_AS_U32 - 1));
1260         // gensym of *existing* string gets new number:
1261         let d = i.intern("dog");
1262         assert_eq!(i.gensymed(d), Symbol::new(SymbolIndex::MAX_AS_U32 - 2));
1263     }
1264
1265     #[test]
1266     fn without_first_quote_test() {
1267         GLOBALS.set(&Globals::new(edition::DEFAULT_EDITION), || {
1268             let i = Ident::from_str("'break");
1269             assert_eq!(i.without_first_quote().name, kw::Break);
1270         });
1271     }
1272 }