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