]> git.lizzy.rs Git - rust.git/blob - src/libsyntax_pos/symbol.rs
Rollup merge of #62585 - pnkfelix:issue-60431-make-struct-tail-normalize-when-possibl...
[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_internals,
512         proc_macro_mod,
513         proc_macro_non_items,
514         proc_macro_path_invoc,
515         profiler_runtime,
516         pub_restricted,
517         pushpop_unsafe,
518         quad_precision_float,
519         question_mark,
520         quote,
521         Range,
522         RangeFrom,
523         RangeFull,
524         RangeInclusive,
525         RangeTo,
526         RangeToInclusive,
527         raw_identifiers,
528         Ready,
529         reason,
530         recursion_limit,
531         reexport_test_harness_main,
532         reflect,
533         relaxed_adts,
534         repr,
535         repr128,
536         repr_align,
537         repr_align_enum,
538         repr_packed,
539         repr_simd,
540         repr_transparent,
541         re_rebalance_coherence,
542         result,
543         Result,
544         Return,
545         rhs,
546         rlib,
547         rt,
548         rtm_target_feature,
549         rust,
550         rust_2015_preview,
551         rust_2018_preview,
552         rust_begin_unwind,
553         rustc,
554         RustcDecodable,
555         RustcEncodable,
556         rustc_allocator,
557         rustc_allocator_nounwind,
558         rustc_allow_const_fn_ptr,
559         rustc_args_required_const,
560         rustc_attrs,
561         rustc_builtin_macro,
562         rustc_clean,
563         rustc_const_unstable,
564         rustc_conversion_suggestion,
565         rustc_copy_clone_marker,
566         rustc_def_path,
567         rustc_deprecated,
568         rustc_diagnostic_macros,
569         rustc_dirty,
570         rustc_dummy,
571         rustc_dump_env_program_clauses,
572         rustc_dump_program_clauses,
573         rustc_dump_user_substs,
574         rustc_error,
575         rustc_expected_cgu_reuse,
576         rustc_if_this_changed,
577         rustc_inherit_overflow_checks,
578         rustc_layout,
579         rustc_layout_scalar_valid_range_end,
580         rustc_layout_scalar_valid_range_start,
581         rustc_macro_transparency,
582         rustc_mir,
583         rustc_nonnull_optimization_guaranteed,
584         rustc_object_lifetime_default,
585         rustc_on_unimplemented,
586         rustc_outlives,
587         rustc_paren_sugar,
588         rustc_partition_codegened,
589         rustc_partition_reused,
590         rustc_peek,
591         rustc_peek_definite_init,
592         rustc_peek_maybe_init,
593         rustc_peek_maybe_uninit,
594         rustc_private,
595         rustc_proc_macro_decls,
596         rustc_promotable,
597         rustc_regions,
598         rustc_stable,
599         rustc_std_internal_symbol,
600         rustc_symbol_name,
601         rustc_synthetic,
602         rustc_test_marker,
603         rustc_then_this_would_need,
604         rustc_variance,
605         rustdoc,
606         rust_eh_personality,
607         rust_eh_unwind_resume,
608         rust_oom,
609         __rust_unstable_column,
610         rvalue_static_promotion,
611         sanitizer_runtime,
612         _Self,
613         self_in_typedefs,
614         self_struct_ctor,
615         should_panic,
616         simd,
617         simd_ffi,
618         since,
619         size,
620         slice_patterns,
621         slicing_syntax,
622         Some,
623         specialization,
624         speed,
625         spotlight,
626         sse4a_target_feature,
627         stable,
628         staged_api,
629         start,
630         static_in_const,
631         staticlib,
632         static_nobundle,
633         static_recursion,
634         std,
635         std_inject,
636         str,
637         stringify,
638         stmt,
639         stmt_expr_attributes,
640         stop_after_dataflow,
641         struct_field_attributes,
642         struct_inherit,
643         structural_match,
644         struct_variant,
645         sty,
646         suggestion,
647         target_feature,
648         target_has_atomic,
649         target_thread_local,
650         task,
651         tbm_target_feature,
652         termination_trait,
653         termination_trait_test,
654         test,
655         test_2018_feature,
656         test_accepted_feature,
657         test_case,
658         test_removed_feature,
659         test_runner,
660         then_with,
661         thread_local,
662         tool_attributes,
663         tool_lints,
664         trace_macros,
665         trait_alias,
666         transmute,
667         transparent,
668         transparent_enums,
669         transparent_unions,
670         trivial_bounds,
671         Try,
672         try_blocks,
673         try_trait,
674         tt,
675         tuple_indexing,
676         Ty,
677         ty,
678         TyCtxt,
679         TyKind,
680         type_alias_enum_variants,
681         type_ascription,
682         type_length_limit,
683         type_macros,
684         u128,
685         u16,
686         u32,
687         u64,
688         u8,
689         unboxed_closures,
690         underscore_const_names,
691         underscore_imports,
692         underscore_lifetimes,
693         uniform_paths,
694         universal_impl_trait,
695         unmarked_api,
696         unreachable_code,
697         unrestricted_attribute_tokens,
698         unsafe_no_drop_flag,
699         unsized_locals,
700         unsized_tuple_coercion,
701         unstable,
702         untagged_unions,
703         unwind,
704         unwind_attributes,
705         unwrap_or,
706         used,
707         use_extern_macros,
708         use_nested_groups,
709         usize,
710         v1,
711         val,
712         vec,
713         Vec,
714         vis,
715         visible_private_types,
716         volatile,
717         warn,
718         warn_directory_ownership,
719         wasm_import_module,
720         wasm_target_feature,
721         while_let,
722         windows,
723         windows_subsystem,
724         Yield,
725     }
726 }
727
728 #[derive(Copy, Clone, Eq)]
729 pub struct Ident {
730     pub name: Symbol,
731     pub span: Span,
732 }
733
734 impl Ident {
735     #[inline]
736     /// Constructs a new identifier from a symbol and a span.
737     pub const fn new(name: Symbol, span: Span) -> Ident {
738         Ident { name, span }
739     }
740
741     /// Constructs a new identifier with an empty syntax context.
742     #[inline]
743     pub const fn with_empty_ctxt(name: Symbol) -> Ident {
744         Ident::new(name, DUMMY_SP)
745     }
746
747     #[inline]
748     pub fn invalid() -> Ident {
749         Ident::with_empty_ctxt(kw::Invalid)
750     }
751
752     /// Maps an interned string to an identifier with an empty syntax context.
753     pub fn from_interned_str(string: InternedString) -> Ident {
754         Ident::with_empty_ctxt(string.as_symbol())
755     }
756
757     /// Maps a string to an identifier with an empty span.
758     pub fn from_str(string: &str) -> Ident {
759         Ident::with_empty_ctxt(Symbol::intern(string))
760     }
761
762     /// Maps a string and a span to an identifier.
763     pub fn from_str_and_span(string: &str, span: Span) -> Ident {
764         Ident::new(Symbol::intern(string), span)
765     }
766
767     /// Replaces `lo` and `hi` with those from `span`, but keep hygiene context.
768     pub fn with_span_pos(self, span: Span) -> Ident {
769         Ident::new(self.name, span.with_ctxt(self.span.ctxt()))
770     }
771
772     pub fn without_first_quote(self) -> Ident {
773         Ident::new(Symbol::intern(self.as_str().trim_start_matches('\'')), self.span)
774     }
775
776     /// "Normalize" ident for use in comparisons using "item hygiene".
777     /// Identifiers with same string value become same if they came from the same "modern" macro
778     /// (e.g., `macro` item, but not `macro_rules` item) and stay different if they came from
779     /// different "modern" macros.
780     /// Technically, this operation strips all non-opaque marks from ident's syntactic context.
781     pub fn modern(self) -> Ident {
782         Ident::new(self.name, self.span.modern())
783     }
784
785     /// "Normalize" ident for use in comparisons using "local variable hygiene".
786     /// Identifiers with same string value become same if they came from the same non-transparent
787     /// macro (e.g., `macro` or `macro_rules!` items) and stay different if they came from different
788     /// non-transparent macros.
789     /// Technically, this operation strips all transparent marks from ident's syntactic context.
790     pub fn modern_and_legacy(self) -> Ident {
791         Ident::new(self.name, self.span.modern_and_legacy())
792     }
793
794     /// Transforms an identifier into one with the same name, but gensymed.
795     pub fn gensym(self) -> Ident {
796         let name = with_interner(|interner| interner.gensymed(self.name));
797         Ident::new(name, self.span)
798     }
799
800     /// Transforms an underscore identifier into one with the same name, but
801     /// gensymed. Leaves non-underscore identifiers unchanged.
802     pub fn gensym_if_underscore(self) -> Ident {
803         if self.name == kw::Underscore { self.gensym() } else { self }
804     }
805
806     // WARNING: this function is deprecated and will be removed in the future.
807     pub fn is_gensymed(self) -> bool {
808         with_interner(|interner| interner.is_gensymed(self.name))
809     }
810
811     pub fn as_str(self) -> LocalInternedString {
812         self.name.as_str()
813     }
814
815     pub fn as_interned_str(self) -> InternedString {
816         self.name.as_interned_str()
817     }
818 }
819
820 impl PartialEq for Ident {
821     fn eq(&self, rhs: &Self) -> bool {
822         self.name == rhs.name && self.span.ctxt() == rhs.span.ctxt()
823     }
824 }
825
826 impl Hash for Ident {
827     fn hash<H: Hasher>(&self, state: &mut H) {
828         self.name.hash(state);
829         self.span.ctxt().hash(state);
830     }
831 }
832
833 impl fmt::Debug for Ident {
834     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
835         write!(f, "{}{:?}", self.name, self.span.ctxt())
836     }
837 }
838
839 impl fmt::Display for Ident {
840     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
841         fmt::Display::fmt(&self.name, f)
842     }
843 }
844
845 impl Encodable for Ident {
846     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
847         if self.span.ctxt().modern() == SyntaxContext::empty() {
848             s.emit_str(&self.as_str())
849         } else { // FIXME(jseyfried): intercrate hygiene
850             let mut string = "#".to_owned();
851             string.push_str(&self.as_str());
852             s.emit_str(&string)
853         }
854     }
855 }
856
857 impl Decodable for Ident {
858     fn decode<D: Decoder>(d: &mut D) -> Result<Ident, D::Error> {
859         let string = d.read_str()?;
860         Ok(if !string.starts_with('#') {
861             Ident::from_str(&string)
862         } else { // FIXME(jseyfried): intercrate hygiene
863             Ident::from_str(&string[1..]).gensym()
864         })
865     }
866 }
867
868 /// A symbol is an interned or gensymed string. A gensym is a symbol that is
869 /// never equal to any other symbol.
870 ///
871 /// Conceptually, a gensym can be thought of as a normal symbol with an
872 /// invisible unique suffix. Gensyms are useful when creating new identifiers
873 /// that must not match any existing identifiers, e.g. during macro expansion
874 /// and syntax desugaring. Because gensyms should always be identifiers, all
875 /// gensym operations are on `Ident` rather than `Symbol`. (Indeed, in the
876 /// future the gensym-ness may be moved from `Symbol` to hygiene data.)
877 ///
878 /// Examples:
879 /// ```
880 /// assert_eq!(Ident::from_str("x"), Ident::from_str("x"))
881 /// assert_ne!(Ident::from_str("x").gensym(), Ident::from_str("x"))
882 /// assert_ne!(Ident::from_str("x").gensym(), Ident::from_str("x").gensym())
883 /// ```
884 /// Internally, a symbol is implemented as an index, and all operations
885 /// (including hashing, equality, and ordering) operate on that index. The use
886 /// of `newtype_index!` means that `Option<Symbol>` only takes up 4 bytes,
887 /// because `newtype_index!` reserves the last 256 values for tagging purposes.
888 ///
889 /// Note that `Symbol` cannot directly be a `newtype_index!` because it
890 /// implements `fmt::Debug`, `Encodable`, and `Decodable` in special ways.
891 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
892 pub struct Symbol(SymbolIndex);
893
894 newtype_index! {
895     pub struct SymbolIndex { .. }
896 }
897
898 impl Symbol {
899     const fn new(n: u32) -> Self {
900         Symbol(SymbolIndex::from_u32_const(n))
901     }
902
903     /// Maps a string to its interned representation.
904     pub fn intern(string: &str) -> Self {
905         with_interner(|interner| interner.intern(string))
906     }
907
908     pub fn as_str(self) -> LocalInternedString {
909         with_interner(|interner| unsafe {
910             LocalInternedString {
911                 string: std::mem::transmute::<&str, &str>(interner.get(self))
912             }
913         })
914     }
915
916     pub fn as_interned_str(self) -> InternedString {
917         with_interner(|interner| InternedString {
918             symbol: interner.interned(self)
919         })
920     }
921
922     pub fn as_u32(self) -> u32 {
923         self.0.as_u32()
924     }
925 }
926
927 impl fmt::Debug for Symbol {
928     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
929         let is_gensymed = with_interner(|interner| interner.is_gensymed(*self));
930         if is_gensymed {
931             write!(f, "{}({:?})", self, self.0)
932         } else {
933             write!(f, "{}", self)
934         }
935     }
936 }
937
938 impl fmt::Display for Symbol {
939     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
940         fmt::Display::fmt(&self.as_str(), f)
941     }
942 }
943
944 impl Encodable for Symbol {
945     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
946         s.emit_str(&self.as_str())
947     }
948 }
949
950 impl Decodable for Symbol {
951     fn decode<D: Decoder>(d: &mut D) -> Result<Symbol, D::Error> {
952         Ok(Symbol::intern(&d.read_str()?))
953     }
954 }
955
956 // The `&'static str`s in this type actually point into the arena.
957 //
958 // Note that normal symbols are indexed upward from 0, and gensyms are indexed
959 // downward from SymbolIndex::MAX_AS_U32.
960 #[derive(Default)]
961 pub struct Interner {
962     arena: DroplessArena,
963     names: FxHashMap<&'static str, Symbol>,
964     strings: Vec<&'static str>,
965     gensyms: Vec<Symbol>,
966 }
967
968 impl Interner {
969     fn prefill(init: &[&'static str]) -> Self {
970         Interner {
971             strings: init.into(),
972             names: init.iter().copied().zip((0..).map(Symbol::new)).collect(),
973             ..Default::default()
974         }
975     }
976
977     pub fn intern(&mut self, string: &str) -> Symbol {
978         if let Some(&name) = self.names.get(string) {
979             return name;
980         }
981
982         let name = Symbol::new(self.strings.len() as u32);
983
984         // `from_utf8_unchecked` is safe since we just allocated a `&str` which is known to be
985         // UTF-8.
986         let string: &str = unsafe {
987             str::from_utf8_unchecked(self.arena.alloc_slice(string.as_bytes()))
988         };
989         // It is safe to extend the arena allocation to `'static` because we only access
990         // these while the arena is still alive.
991         let string: &'static str =  unsafe {
992             &*(string as *const str)
993         };
994         self.strings.push(string);
995         self.names.insert(string, name);
996         name
997     }
998
999     fn interned(&self, symbol: Symbol) -> Symbol {
1000         if (symbol.0.as_usize()) < self.strings.len() {
1001             symbol
1002         } else {
1003             self.gensyms[(SymbolIndex::MAX_AS_U32 - symbol.0.as_u32()) as usize]
1004         }
1005     }
1006
1007     fn gensymed(&mut self, symbol: Symbol) -> Symbol {
1008         self.gensyms.push(symbol);
1009         Symbol::new(SymbolIndex::MAX_AS_U32 - self.gensyms.len() as u32 + 1)
1010     }
1011
1012     fn is_gensymed(&mut self, symbol: Symbol) -> bool {
1013         symbol.0.as_usize() >= self.strings.len()
1014     }
1015
1016     // Get the symbol as a string. `Symbol::as_str()` should be used in
1017     // preference to this function.
1018     pub fn get(&self, symbol: Symbol) -> &str {
1019         match self.strings.get(symbol.0.as_usize()) {
1020             Some(string) => string,
1021             None => {
1022                 let symbol = self.gensyms[(SymbolIndex::MAX_AS_U32 - symbol.0.as_u32()) as usize];
1023                 self.strings[symbol.0.as_usize()]
1024             }
1025         }
1026     }
1027 }
1028
1029 // This module has a very short name because it's used a lot.
1030 pub mod kw {
1031     use super::Symbol;
1032     keywords!();
1033 }
1034
1035 // This module has a very short name because it's used a lot.
1036 pub mod sym {
1037     use std::convert::TryInto;
1038     use super::Symbol;
1039
1040     symbols!();
1041
1042     // Get the symbol for an integer. The first few non-negative integers each
1043     // have a static symbol and therefore are fast.
1044     pub fn integer<N: TryInto<usize> + Copy + ToString>(n: N) -> Symbol {
1045         if let Result::Ok(idx) = n.try_into() {
1046             if let Option::Some(&sym) = digits_array.get(idx) {
1047                 return sym;
1048             }
1049         }
1050         Symbol::intern(&n.to_string())
1051     }
1052 }
1053
1054 impl Symbol {
1055     fn is_used_keyword_2018(self) -> bool {
1056         self == kw::Dyn
1057     }
1058
1059     fn is_unused_keyword_2018(self) -> bool {
1060         self >= kw::Async && self <= kw::Try
1061     }
1062
1063     /// Used for sanity checking rustdoc keyword sections.
1064     pub fn is_doc_keyword(self) -> bool {
1065         self <= kw::Union
1066     }
1067
1068     /// A keyword or reserved identifier that can be used as a path segment.
1069     pub fn is_path_segment_keyword(self) -> bool {
1070         self == kw::Super ||
1071         self == kw::SelfLower ||
1072         self == kw::SelfUpper ||
1073         self == kw::Crate ||
1074         self == kw::PathRoot ||
1075         self == kw::DollarCrate
1076     }
1077
1078     /// This symbol can be a raw identifier.
1079     pub fn can_be_raw(self) -> bool {
1080         self != kw::Invalid && self != kw::Underscore && !self.is_path_segment_keyword()
1081     }
1082 }
1083
1084 impl Ident {
1085     // Returns `true` for reserved identifiers used internally for elided lifetimes,
1086     // unnamed method parameters, crate root module, error recovery etc.
1087     pub fn is_special(self) -> bool {
1088         self.name <= kw::Underscore
1089     }
1090
1091     /// Returns `true` if the token is a keyword used in the language.
1092     pub fn is_used_keyword(self) -> bool {
1093         // Note: `span.edition()` is relatively expensive, don't call it unless necessary.
1094         self.name >= kw::As && self.name <= kw::While ||
1095         self.name.is_used_keyword_2018() && self.span.rust_2018()
1096     }
1097
1098     /// Returns `true` if the token is a keyword reserved for possible future use.
1099     pub fn is_unused_keyword(self) -> bool {
1100         // Note: `span.edition()` is relatively expensive, don't call it unless necessary.
1101         self.name >= kw::Abstract && self.name <= kw::Yield ||
1102         self.name.is_unused_keyword_2018() && self.span.rust_2018()
1103     }
1104
1105     /// Returns `true` if the token is either a special identifier or a keyword.
1106     pub fn is_reserved(self) -> bool {
1107         self.is_special() || self.is_used_keyword() || self.is_unused_keyword()
1108     }
1109
1110     /// A keyword or reserved identifier that can be used as a path segment.
1111     pub fn is_path_segment_keyword(self) -> bool {
1112         self.name.is_path_segment_keyword()
1113     }
1114
1115     /// We see this identifier in a normal identifier position, like variable name or a type.
1116     /// How was it written originally? Did it use the raw form? Let's try to guess.
1117     pub fn is_raw_guess(self) -> bool {
1118         self.name.can_be_raw() && self.is_reserved()
1119     }
1120 }
1121
1122 // If an interner exists, return it. Otherwise, prepare a fresh one.
1123 #[inline]
1124 fn with_interner<T, F: FnOnce(&mut Interner) -> T>(f: F) -> T {
1125     GLOBALS.with(|globals| f(&mut *globals.symbol_interner.lock()))
1126 }
1127
1128 /// An alternative to `Symbol` and `InternedString`, useful when the chars
1129 /// within the symbol need to be accessed. It is best used for temporary
1130 /// values.
1131 ///
1132 /// Because the interner outlives any thread which uses this type, we can
1133 /// safely treat `string` which points to interner data, as an immortal string,
1134 /// as long as this type never crosses between threads.
1135 //
1136 // FIXME: ensure that the interner outlives any thread which uses
1137 // `LocalInternedString`, by creating a new thread right after constructing the
1138 // interner.
1139 #[derive(Clone, Copy, Hash, PartialOrd, Eq, Ord)]
1140 pub struct LocalInternedString {
1141     string: &'static str,
1142 }
1143
1144 impl LocalInternedString {
1145     /// Maps a string to its interned representation.
1146     pub fn intern(string: &str) -> Self {
1147         let string = with_interner(|interner| {
1148             let symbol = interner.intern(string);
1149             interner.strings[symbol.0.as_usize()]
1150         });
1151         LocalInternedString {
1152             string: unsafe { std::mem::transmute::<&str, &str>(string) }
1153         }
1154     }
1155
1156     pub fn as_interned_str(self) -> InternedString {
1157         InternedString {
1158             symbol: Symbol::intern(self.string)
1159         }
1160     }
1161
1162     #[inline]
1163     pub fn get(&self) -> &str {
1164         // This returns a valid string since we ensure that `self` outlives the interner
1165         // by creating the interner on a thread which outlives threads which can access it.
1166         // This type cannot move to a thread which outlives the interner since it does
1167         // not implement Send.
1168         self.string
1169     }
1170 }
1171
1172 impl<U: ?Sized> std::convert::AsRef<U> for LocalInternedString
1173 where
1174     str: std::convert::AsRef<U>
1175 {
1176     #[inline]
1177     fn as_ref(&self) -> &U {
1178         self.string.as_ref()
1179     }
1180 }
1181
1182 impl<T: std::ops::Deref<Target = str>> std::cmp::PartialEq<T> for LocalInternedString {
1183     fn eq(&self, other: &T) -> bool {
1184         self.string == other.deref()
1185     }
1186 }
1187
1188 impl std::cmp::PartialEq<LocalInternedString> for str {
1189     fn eq(&self, other: &LocalInternedString) -> bool {
1190         self == other.string
1191     }
1192 }
1193
1194 impl<'a> std::cmp::PartialEq<LocalInternedString> for &'a str {
1195     fn eq(&self, other: &LocalInternedString) -> bool {
1196         *self == other.string
1197     }
1198 }
1199
1200 impl std::cmp::PartialEq<LocalInternedString> for String {
1201     fn eq(&self, other: &LocalInternedString) -> bool {
1202         self == other.string
1203     }
1204 }
1205
1206 impl<'a> std::cmp::PartialEq<LocalInternedString> for &'a String {
1207     fn eq(&self, other: &LocalInternedString) -> bool {
1208         *self == other.string
1209     }
1210 }
1211
1212 impl !Send for LocalInternedString {}
1213 impl !Sync for LocalInternedString {}
1214
1215 impl std::ops::Deref for LocalInternedString {
1216     type Target = str;
1217     #[inline]
1218     fn deref(&self) -> &str { self.string }
1219 }
1220
1221 impl fmt::Debug for LocalInternedString {
1222     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1223         fmt::Debug::fmt(self.string, f)
1224     }
1225 }
1226
1227 impl fmt::Display for LocalInternedString {
1228     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1229         fmt::Display::fmt(self.string, f)
1230     }
1231 }
1232
1233 impl Decodable for LocalInternedString {
1234     fn decode<D: Decoder>(d: &mut D) -> Result<LocalInternedString, D::Error> {
1235         Ok(LocalInternedString::intern(&d.read_str()?))
1236     }
1237 }
1238
1239 impl Encodable for LocalInternedString {
1240     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
1241         s.emit_str(self.string)
1242     }
1243 }
1244
1245 /// An alternative to `Symbol` that is focused on string contents. It has two
1246 /// main differences to `Symbol`.
1247 ///
1248 /// First, its implementations of `Hash`, `PartialOrd` and `Ord` work with the
1249 /// string chars rather than the symbol integer. This is useful when hash
1250 /// stability is required across compile sessions, or a guaranteed sort
1251 /// ordering is required.
1252 ///
1253 /// Second, gensym-ness is irrelevant. E.g.:
1254 /// ```
1255 /// assert_ne!(Symbol::gensym("x"), Symbol::gensym("x"))
1256 /// assert_eq!(Symbol::gensym("x").as_interned_str(), Symbol::gensym("x").as_interned_str())
1257 /// ```
1258 #[derive(Clone, Copy, PartialEq, Eq)]
1259 pub struct InternedString {
1260     symbol: Symbol,
1261 }
1262
1263 impl InternedString {
1264     /// Maps a string to its interned representation.
1265     pub fn intern(string: &str) -> Self {
1266         InternedString {
1267             symbol: Symbol::intern(string)
1268         }
1269     }
1270
1271     pub fn with<F: FnOnce(&str) -> R, R>(self, f: F) -> R {
1272         let str = with_interner(|interner| {
1273             interner.get(self.symbol) as *const str
1274         });
1275         // This is safe because the interner keeps string alive until it is dropped.
1276         // We can access it because we know the interner is still alive since we use a
1277         // scoped thread local to access it, and it was alive at the beginning of this scope
1278         unsafe { f(&*str) }
1279     }
1280
1281     fn with2<F: FnOnce(&str, &str) -> R, R>(self, other: &InternedString, f: F) -> R {
1282         let (self_str, other_str) = with_interner(|interner| {
1283             (interner.get(self.symbol) as *const str,
1284              interner.get(other.symbol) as *const str)
1285         });
1286         // This is safe for the same reason that `with` is safe.
1287         unsafe { f(&*self_str, &*other_str) }
1288     }
1289
1290     pub fn as_symbol(self) -> Symbol {
1291         self.symbol
1292     }
1293
1294     pub fn as_str(self) -> LocalInternedString {
1295         self.symbol.as_str()
1296     }
1297 }
1298
1299 impl Hash for InternedString {
1300     fn hash<H: Hasher>(&self, state: &mut H) {
1301         self.with(|str| str.hash(state))
1302     }
1303 }
1304
1305 impl PartialOrd<InternedString> for InternedString {
1306     fn partial_cmp(&self, other: &InternedString) -> Option<Ordering> {
1307         if self.symbol == other.symbol {
1308             return Some(Ordering::Equal);
1309         }
1310         self.with2(other, |self_str, other_str| self_str.partial_cmp(other_str))
1311     }
1312 }
1313
1314 impl Ord for InternedString {
1315     fn cmp(&self, other: &InternedString) -> Ordering {
1316         if self.symbol == other.symbol {
1317             return Ordering::Equal;
1318         }
1319         self.with2(other, |self_str, other_str| self_str.cmp(other_str))
1320     }
1321 }
1322
1323 impl fmt::Debug for InternedString {
1324     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1325         self.with(|str| fmt::Debug::fmt(&str, f))
1326     }
1327 }
1328
1329 impl fmt::Display for InternedString {
1330     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1331         self.with(|str| fmt::Display::fmt(&str, f))
1332     }
1333 }
1334
1335 impl Decodable for InternedString {
1336     fn decode<D: Decoder>(d: &mut D) -> Result<InternedString, D::Error> {
1337         Ok(InternedString::intern(&d.read_str()?))
1338     }
1339 }
1340
1341 impl Encodable for InternedString {
1342     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
1343         self.with(|string| s.emit_str(string))
1344     }
1345 }
1346
1347 #[cfg(test)]
1348 mod tests {
1349     use super::*;
1350     use crate::Globals;
1351     use crate::edition;
1352
1353     #[test]
1354     fn interner_tests() {
1355         let mut i: Interner = Interner::default();
1356         // first one is zero:
1357         assert_eq!(i.intern("dog"), Symbol::new(0));
1358         // re-use gets the same entry:
1359         assert_eq!(i.intern("dog"), Symbol::new(0));
1360         // different string gets a different #:
1361         assert_eq!(i.intern("cat"), Symbol::new(1));
1362         assert_eq!(i.intern("cat"), Symbol::new(1));
1363         // dog is still at zero
1364         assert_eq!(i.intern("dog"), Symbol::new(0));
1365         let z = i.intern("zebra");
1366         assert_eq!(i.gensymed(z), Symbol::new(SymbolIndex::MAX_AS_U32));
1367         // gensym of same string gets new number:
1368         assert_eq!(i.gensymed(z), Symbol::new(SymbolIndex::MAX_AS_U32 - 1));
1369         // gensym of *existing* string gets new number:
1370         let d = i.intern("dog");
1371         assert_eq!(i.gensymed(d), Symbol::new(SymbolIndex::MAX_AS_U32 - 2));
1372     }
1373
1374     #[test]
1375     fn without_first_quote_test() {
1376         GLOBALS.set(&Globals::new(edition::DEFAULT_EDITION), || {
1377             let i = Ident::from_str("'break");
1378             assert_eq!(i.without_first_quote().name, kw::Break);
1379         });
1380     }
1381 }