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