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