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