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.
5 use rustc_arena
::DroplessArena
;
6 use rustc_data_structures
::fx
::FxHashMap
;
7 use rustc_data_structures
::stable_hasher
::{HashStable, StableHasher, ToStableHashKey}
;
8 use rustc_data_structures
::sync
::Lock
;
9 use rustc_macros
::HashStable_Generic
;
10 use rustc_serialize
::{Decodable, Decoder, Encodable, Encoder}
;
12 use std
::cmp
::{Ord, PartialEq, PartialOrd}
;
14 use std
::hash
::{Hash, Hasher}
;
17 use crate::{with_session_globals, Edition, Span, DUMMY_SP}
;
22 // The proc macro code for this is in `compiler/rustc_macros/src/symbols.rs`.
24 // After modifying this list adjust `is_special`, `is_used_keyword`/`is_unused_keyword`,
25 // this should be rarely necessary though if the keywords are kept in alphabetic order.
27 // Special reserved identifiers used internally for elided lifetimes,
28 // unnamed method parameters, crate root module, error recovery etc.
31 DollarCrate
: "$crate",
34 // Keywords that are used in stable Rust.
71 // Keywords that are used in unstable Rust or reserved for future use.
85 // Edition-specific keywords that are used in stable Rust.
86 Async
: "async", // >= 2018 Edition only
87 Await
: "await", // >= 2018 Edition only
88 Dyn
: "dyn", // >= 2018 Edition only
90 // Edition-specific keywords that are used in unstable Rust or reserved for future use.
91 Try
: "try", // >= 2018 Edition only
93 // Special lifetime names
94 UnderscoreLifetime
: "'_",
95 StaticLifetime
: "'static",
97 // Weak keywords, have special meaning only in specific contexts.
101 MacroRules
: "macro_rules",
107 // Pre-interned symbols that can be referred to with `rustc_span::sym::*`.
109 // The symbol is the stringified identifier unless otherwise specified, in
110 // which case the name should mention the non-identifier punctuation.
111 // E.g. `sym::proc_dash_macro` represents "proc-macro", and it shouldn't be
112 // called `sym::proc_macro` because then it's easy to mistakenly think it
113 // represents "proc_macro".
115 // As well as the symbols listed, there are symbols for the strings
116 // "0", "1", ..., "9", which are accessible via `sym::integer`.
118 // The proc macro will abort if symbols are not in alphabetical order (as
119 // defined by `impl Ord for str`) or if any symbols are duplicated. Vim
120 // users can sort the list by selecting it and executing the command
121 // `:'<,'>!LC_ALL=C sort`.
123 // There is currently no checking that all symbols are used; that would be
260 ProceduralMasqueradeDummyType
,
289 SubdiagnosticMessage
,
320 aarch64_target_feature
,
321 aarch64_ver_target_feature
,
325 abi_c_cmse_nonsecure_call
,
327 abi_msp430_interrupt
,
341 advanced_slice_patterns
,
358 allow_internal_unsafe
,
359 allow_internal_unstable
,
365 anonymous_lifetime_in_impl_trait
,
368 arbitrary_enum_discriminant
,
369 arbitrary_self_types
,
381 asm_experimental_arch
,
389 assert_receiver_is_total_eq
,
393 associated_const_equality
,
395 associated_type_bounds
,
396 associated_type_defaults
,
410 augmented_assignments
,
412 automatically_derived
,
414 avx512_target_feature
,
422 bind_by_move_pattern_guards
,
434 borrowck_graphviz_format
,
435 borrowck_graphviz_postflow
,
436 borrowck_graphviz_preflow
,
441 braced_empty_structs
,
453 capture_disjoint_fields
,
471 cfg_target_has_atomic
,
472 cfg_target_has_atomic_equal_alignment
,
473 cfg_target_has_atomic_load_store
,
474 cfg_target_thread_local
,
486 closure_lifetime_binder
,
487 closure_to_fn_coercion
,
488 closure_track_caller
,
492 cmpxchg16b_target_feature
,
493 cmse_nonsecure_entry
,
501 compare_exchange_weak
,
511 conservative_impl_trait
,
515 const_compare_raw_pointers
,
520 const_evaluatable_checked
,
523 const_fn_floating_point_arithmetic
,
524 const_fn_fn_ptr_basics
,
525 const_fn_trait_bound
,
531 const_generic_defaults
,
533 const_generics_defaults
,
536 const_in_array_repeat_expressions
,
543 const_precise_live_drops
,
545 const_raw_ptr_to_usize_cast
,
548 const_trait_bound_opt_out
,
565 core_panic_2015_macro
,
576 crate_visibility_modifier
,
577 crt_dash_static
: "crt-static",
586 custom_inner_attributes
,
587 custom_test_frameworks
,
594 debug_assert_eq_macro
,
596 debug_assert_ne_macro
,
599 debug_struct_fields_finish
,
602 debug_tuple_fields_finish
,
607 default_alloc_error_handler
,
608 default_lib_allocator
,
609 default_method_body_is_const
,
610 default_type_parameter_fallback
,
612 delay_span_bug_from_inside_query
,
616 deprecated_suggestion
,
624 destructuring_assignment
,
645 document_private_items
,
647 dotdot_in_tuple_patterns
,
648 dotdoteq_in_patterns
,
656 dropck_parametricity
,
668 emit_enum_variant_arg
,
679 ermsb_target_feature
,
683 exclusive_range_pattern
,
684 exhaustive_integer_patterns
,
693 explicit_generic_args_with_impl_trait
,
696 extended_key_value_attributes
,
697 extern_absolute_paths
,
698 extern_crate_item_prelude
,
722 field_init_shorthand
,
729 float_to_int_unchecked
,
762 from_size_align_unchecked
,
779 generic_associated_types
,
780 generic_associated_types_extended
,
788 half_open_range_patterns
,
789 half_open_range_patterns_in_slices
,
791 hexagon_target_feature
,
793 homogeneous_aggregate
,
810 if_while_or_patterns
,
812 impl_header_lifetime_elision
,
815 impl_trait_in_bindings
,
828 inclusive_range_syntax
,
831 infer_outlives_requirements
,
832 infer_static_outlives_requirements
,
833 inherent_associated_types
,
848 irrefutable_let_patterns
,
852 issue_5723_bootstrap
,
853 issue_tracker_base_url
,
868 lazy_normalization_consts
,
884 link_llvm_intrinsics
,
905 macro_at_most_once_rep
,
906 macro_attributes_in_derive_output
,
909 macro_lifetime_matcher
,
910 macro_literal_matcher
,
923 match_beginning_vert
,
924 match_default_bindings
,
954 min_type_alias_impl_trait
,
965 more_qualified_paths
,
967 movbe_target_feature
,
979 native_link_modifiers
,
980 native_link_modifiers_as_needed
,
981 native_link_modifiers_bundle
,
982 native_link_modifiers_verbatim
,
983 native_link_modifiers_whole_archive
,
1020 no_implicit_prelude
,
1032 non_exhaustive_omitted_patterns_lint
,
1044 object_safe_for_dispatch
,
1047 omit_gdb_pretty_printer_section
,
1056 optin_builtin_traits
,
1065 overlapping_marker_traits
,
1077 panic_implementation
,
1093 pattern_parentheses
,
1096 platform_intrinsics
,
1105 post_dash_lto
: "post-lto",
1106 powerpc_target_feature
,
1111 pre_dash_lto
: "pre-lto",
1112 precise_pointer_size_matching
,
1116 prefetch_read_instruction
,
1117 prefetch_write_data
,
1118 prefetch_write_instruction
,
1126 proc_dash_macro
: "proc-macro",
1128 proc_macro_attribute
,
1129 proc_macro_def_site
,
1134 proc_macro_internals
,
1136 proc_macro_non_items
,
1137 proc_macro_path_invoc
,
1146 ptr_offset_from_unsigned
,
1155 quad_precision_float
,
1158 range_inclusive_new
,
1163 re_rebalance_coherence
,
1166 read_enum_variant_arg
,
1174 reexport_test_harness_main
,
1175 ref_unwind_safe_trait
,
1192 relaxed_struct_unsize
,
1205 return_position_impl_trait_in_trait
,
1209 riscv_target_feature
,
1228 rust_eh_catch_typeinfo
,
1229 rust_eh_personality
,
1230 rust_eh_register_frames
,
1231 rust_eh_unregister_frames
,
1235 rustc_allocator_zeroed
,
1236 rustc_allow_const_fn_unstable
,
1237 rustc_allow_incoherent_impl
,
1238 rustc_allowed_through_unstable_modules
,
1241 rustc_builtin_macro
,
1242 rustc_capture_analysis
,
1244 rustc_coherence_is_core
,
1246 rustc_const_unstable
,
1247 rustc_conversion_suggestion
,
1250 rustc_default_body_unstable
,
1251 rustc_diagnostic_item
,
1252 rustc_diagnostic_macros
,
1254 rustc_do_not_const_check
,
1256 rustc_dump_env_program_clauses
,
1257 rustc_dump_program_clauses
,
1258 rustc_dump_user_substs
,
1260 rustc_effective_visibility
,
1262 rustc_evaluate_where_clauses
,
1263 rustc_expected_cgu_reuse
,
1264 rustc_has_incoherent_inherent_impls
,
1265 rustc_if_this_changed
,
1266 rustc_inherit_overflow_checks
,
1267 rustc_insignificant_dtor
,
1269 rustc_layout_scalar_valid_range_end
,
1270 rustc_layout_scalar_valid_range_start
,
1271 rustc_legacy_const_generics
,
1272 rustc_lint_diagnostics
,
1273 rustc_lint_opt_deny_field_access
,
1275 rustc_lint_query_instability
,
1276 rustc_macro_transparency
,
1279 rustc_must_implement_one_of
,
1280 rustc_nonnull_optimization_guaranteed
,
1282 rustc_object_lifetime_default
,
1283 rustc_on_unimplemented
,
1286 rustc_partition_codegened
,
1287 rustc_partition_reused
,
1288 rustc_pass_by_value
,
1290 rustc_peek_definite_init
,
1291 rustc_peek_liveness
,
1292 rustc_peek_maybe_init
,
1293 rustc_peek_maybe_uninit
,
1294 rustc_polymorphize_error
,
1296 rustc_proc_macro_decls
,
1300 rustc_reservation_impl
,
1301 rustc_safe_intrinsic
,
1303 rustc_skip_array_during_method_dispatch
,
1304 rustc_specialization_trait
,
1306 rustc_std_internal_symbol
,
1307 rustc_strict_coherence
,
1310 rustc_then_this_would_need
,
1311 rustc_trivial_field_reads
,
1312 rustc_unsafe_specialization_marker
,
1316 rustdoc_missing_doc_code_examples
,
1318 rvalue_static_promotion
,
1363 simd_from_exposed_addr
,
1376 simd_reduce_add_ordered
,
1377 simd_reduce_add_unordered
,
1382 simd_reduce_max_nanless
,
1384 simd_reduce_min_nanless
,
1385 simd_reduce_mul_ordered
,
1386 simd_reduce_mul_unordered
,
1391 simd_saturating_add
,
1392 simd_saturating_sub
,
1395 simd_select_bitmask
,
1423 sse4a_target_feature
,
1435 std_panic_2015_macro
,
1438 stmt_expr_attributes
,
1439 stop_after_dataflow
,
1442 str_split_whitespace
,
1449 struct_field_attributes
,
1472 target_has_atomic_equal_alignment
,
1473 target_has_atomic_load_store
,
1475 target_pointer_width
,
1476 target_target_vendor
,
1477 target_thread_local
,
1483 termination_trait_test
,
1486 test_accepted_feature
,
1488 test_removed_feature
,
1496 thumb_mode
: "thumb-mode",
1528 type_alias_enum_variants
,
1529 type_alias_impl_trait
,
1531 type_changing_struct_update
,
1541 unaligned_volatile_load
,
1542 unaligned_volatile_store
,
1551 underscore_const_names
,
1553 underscore_lifetimes
,
1555 unimplemented_macro
,
1557 universal_impl_trait
,
1565 unreachable_2015_macro
,
1567 unreachable_2021_macro
,
1569 unreachable_display
,
1571 unrestricted_attribute_tokens
,
1572 unsafe_block_in_unsafe_fn
,
1574 unsafe_no_drop_flag
,
1575 unsafe_pin_internals
,
1579 unsized_tuple_coercion
,
1581 unstable_location_reason_default
: "this crate is being loaded from the sysroot, an \
1582 unstable location; did you mean to load this crate \
1583 from crates.io via `Cargo.toml` instead?",
1586 unused_qualifications
,
1614 visible_private_types
,
1616 volatile_copy_memory
,
1617 volatile_copy_nonoverlapping_memory
,
1619 volatile_set_memory
,
1628 wasm_target_feature
,
1633 with_negative_coherence
,
1645 yeet_desugar_details
,
1652 #[derive(Copy, Clone, Eq, HashStable_Generic, Encodable, Decodable)]
1660 /// Constructs a new identifier from a symbol and a span.
1661 pub const fn new(name
: Symbol
, span
: Span
) -> Ident
{
1662 Ident { name, span }
1665 /// Constructs a new identifier with a dummy span.
1667 pub const fn with_dummy_span(name
: Symbol
) -> Ident
{
1668 Ident
::new(name
, DUMMY_SP
)
1672 pub fn empty() -> Ident
{
1673 Ident
::with_dummy_span(kw
::Empty
)
1676 /// Maps a string to an identifier with a dummy span.
1677 pub fn from_str(string
: &str) -> Ident
{
1678 Ident
::with_dummy_span(Symbol
::intern(string
))
1681 /// Maps a string and a span to an identifier.
1682 pub fn from_str_and_span(string
: &str, span
: Span
) -> Ident
{
1683 Ident
::new(Symbol
::intern(string
), span
)
1686 /// Replaces `lo` and `hi` with those from `span`, but keep hygiene context.
1687 pub fn with_span_pos(self, span
: Span
) -> Ident
{
1688 Ident
::new(self.name
, span
.with_ctxt(self.span
.ctxt()))
1691 pub fn without_first_quote(self) -> Ident
{
1692 Ident
::new(Symbol
::intern(self.as_str().trim_start_matches('
\''
)), self.span
)
1695 /// "Normalize" ident for use in comparisons using "item hygiene".
1696 /// Identifiers with same string value become same if they came from the same macro 2.0 macro
1697 /// (e.g., `macro` item, but not `macro_rules` item) and stay different if they came from
1698 /// different macro 2.0 macros.
1699 /// Technically, this operation strips all non-opaque marks from ident's syntactic context.
1700 pub fn normalize_to_macros_2_0(self) -> Ident
{
1701 Ident
::new(self.name
, self.span
.normalize_to_macros_2_0())
1704 /// "Normalize" ident for use in comparisons using "local variable hygiene".
1705 /// Identifiers with same string value become same if they came from the same non-transparent
1706 /// macro (e.g., `macro` or `macro_rules!` items) and stay different if they came from different
1707 /// non-transparent macros.
1708 /// Technically, this operation strips all transparent marks from ident's syntactic context.
1710 pub fn normalize_to_macro_rules(self) -> Ident
{
1711 Ident
::new(self.name
, self.span
.normalize_to_macro_rules())
1714 /// Access the underlying string. This is a slowish operation because it
1715 /// requires locking the symbol interner.
1717 /// Note that the lifetime of the return value is a lie. See
1718 /// `Symbol::as_str()` for details.
1719 pub fn as_str(&self) -> &str {
1724 impl PartialEq
for Ident
{
1726 fn eq(&self, rhs
: &Self) -> bool
{
1727 self.name
== rhs
.name
&& self.span
.eq_ctxt(rhs
.span
)
1731 impl Hash
for Ident
{
1732 fn hash
<H
: Hasher
>(&self, state
: &mut H
) {
1733 self.name
.hash(state
);
1734 self.span
.ctxt().hash(state
);
1738 impl fmt
::Debug
for Ident
{
1739 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
1740 fmt
::Display
::fmt(self, f
)?
;
1741 fmt
::Debug
::fmt(&self.span
.ctxt(), f
)
1745 /// This implementation is supposed to be used in error messages, so it's expected to be identical
1746 /// to printing the original identifier token written in source code (`token_to_string`),
1747 /// except that AST identifiers don't keep the rawness flag, so we have to guess it.
1748 impl fmt
::Display
for Ident
{
1749 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
1750 fmt
::Display
::fmt(&IdentPrinter
::new(self.name
, self.is_raw_guess(), None
), f
)
1754 /// This is the most general way to print identifiers.
1755 /// AST pretty-printer is used as a fallback for turning AST structures into token streams for
1756 /// proc macros. Additionally, proc macros may stringify their input and expect it survive the
1757 /// stringification (especially true for proc macro derives written between Rust 1.15 and 1.30).
1758 /// So we need to somehow pretty-print `$crate` in a way preserving at least some of its
1759 /// hygiene data, most importantly name of the crate it refers to.
1760 /// As a result we print `$crate` as `crate` if it refers to the local crate
1761 /// and as `::other_crate_name` if it refers to some other crate.
1762 /// Note, that this is only done if the ident token is printed from inside of AST pretty-printing,
1763 /// but not otherwise. Pretty-printing is the only way for proc macros to discover token contents,
1764 /// so we should not perform this lossy conversion if the top level call to the pretty-printer was
1765 /// done for a token stream or a single token.
1766 pub struct IdentPrinter
{
1769 /// Span used for retrieving the crate name to which `$crate` refers to,
1770 /// if this field is `None` then the `$crate` conversion doesn't happen.
1771 convert_dollar_crate
: Option
<Span
>,
1775 /// The most general `IdentPrinter` constructor. Do not use this.
1776 pub fn new(symbol
: Symbol
, is_raw
: bool
, convert_dollar_crate
: Option
<Span
>) -> IdentPrinter
{
1777 IdentPrinter { symbol, is_raw, convert_dollar_crate }
1780 /// This implementation is supposed to be used when printing identifiers
1781 /// as a part of pretty-printing for larger AST pieces.
1782 /// Do not use this either.
1783 pub fn for_ast_ident(ident
: Ident
, is_raw
: bool
) -> IdentPrinter
{
1784 IdentPrinter
::new(ident
.name
, is_raw
, Some(ident
.span
))
1788 impl fmt
::Display
for IdentPrinter
{
1789 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
1792 } else if self.symbol
== kw
::DollarCrate
{
1793 if let Some(span
) = self.convert_dollar_crate
{
1794 let converted
= span
.ctxt().dollar_crate_name();
1795 if !converted
.is_path_segment_keyword() {
1798 return fmt
::Display
::fmt(&converted
, f
);
1801 fmt
::Display
::fmt(&self.symbol
, f
)
1805 /// An newtype around `Ident` that calls [Ident::normalize_to_macro_rules] on
1807 // FIXME(matthewj, petrochenkov) Use this more often, add a similar
1808 // `ModernIdent` struct and use that as well.
1809 #[derive(Copy, Clone, Eq, PartialEq, Hash)]
1810 pub struct MacroRulesNormalizedIdent(Ident
);
1812 impl MacroRulesNormalizedIdent
{
1813 pub fn new(ident
: Ident
) -> Self {
1814 Self(ident
.normalize_to_macro_rules())
1818 impl fmt
::Debug
for MacroRulesNormalizedIdent
{
1819 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
1820 fmt
::Debug
::fmt(&self.0, f
)
1824 impl fmt
::Display
for MacroRulesNormalizedIdent
{
1825 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
1826 fmt
::Display
::fmt(&self.0, f
)
1830 /// An interned string.
1832 /// Internally, a `Symbol` is implemented as an index, and all operations
1833 /// (including hashing, equality, and ordering) operate on that index. The use
1834 /// of `rustc_index::newtype_index!` means that `Option<Symbol>` only takes up 4 bytes,
1835 /// because `rustc_index::newtype_index!` reserves the last 256 values for tagging purposes.
1837 /// Note that `Symbol` cannot directly be a `rustc_index::newtype_index!` because it
1838 /// implements `fmt::Debug`, `Encodable`, and `Decodable` in special ways.
1839 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
1840 pub struct Symbol(SymbolIndex
);
1842 rustc_index
::newtype_index
! {
1843 struct SymbolIndex { .. }
1847 const fn new(n
: u32) -> Self {
1848 Symbol(SymbolIndex
::from_u32(n
))
1851 /// for use in Decoder only
1852 pub fn new_from_decoded(n
: u32) -> Self {
1856 /// Maps a string to its interned representation.
1857 pub fn intern(string
: &str) -> Self {
1858 with_session_globals(|session_globals
| session_globals
.symbol_interner
.intern(string
))
1861 /// Access the underlying string. This is a slowish operation because it
1862 /// requires locking the symbol interner.
1864 /// Note that the lifetime of the return value is a lie. It's not the same
1865 /// as `&self`, but actually tied to the lifetime of the underlying
1866 /// interner. Interners are long-lived, and there are very few of them, and
1867 /// this function is typically used for short-lived things, so in practice
1868 /// it works out ok.
1869 pub fn as_str(&self) -> &str {
1870 with_session_globals(|session_globals
| unsafe {
1871 std
::mem
::transmute
::<&str, &str>(session_globals
.symbol_interner
.get(*self))
1875 pub fn as_u32(self) -> u32 {
1879 pub fn is_empty(self) -> bool
{
1883 /// This method is supposed to be used in error messages, so it's expected to be
1884 /// identical to printing the original identifier token written in source code
1885 /// (`token_to_string`, `Ident::to_string`), except that symbols don't keep the rawness flag
1886 /// or edition, so we have to guess the rawness using the global edition.
1887 pub fn to_ident_string(self) -> String
{
1888 Ident
::with_dummy_span(self).to_string()
1892 impl fmt
::Debug
for Symbol
{
1893 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
1894 fmt
::Debug
::fmt(self.as_str(), f
)
1898 impl fmt
::Display
for Symbol
{
1899 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
1900 fmt
::Display
::fmt(self.as_str(), f
)
1904 // takes advantage of `str::to_string` specialization
1905 impl ToString
for Symbol
{
1906 fn to_string(&self) -> String
{
1907 self.as_str().to_string()
1911 impl<S
: Encoder
> Encodable
<S
> for Symbol
{
1912 default fn encode(&self, s
: &mut S
) {
1913 s
.emit_str(self.as_str());
1917 impl<D
: Decoder
> Decodable
<D
> for Symbol
{
1919 default fn decode(d
: &mut D
) -> Symbol
{
1920 Symbol
::intern(&d
.read_str())
1924 impl<CTX
> HashStable
<CTX
> for Symbol
{
1926 fn hash_stable(&self, hcx
: &mut CTX
, hasher
: &mut StableHasher
) {
1927 self.as_str().hash_stable(hcx
, hasher
);
1931 impl<CTX
> ToStableHashKey
<CTX
> for Symbol
{
1932 type KeyType
= String
;
1934 fn to_stable_hash_key(&self, _
: &CTX
) -> String
{
1935 self.as_str().to_string()
1940 pub(crate) struct Interner(Lock
<InternerInner
>);
1942 // The `&'static str`s in this type actually point into the arena.
1944 // The `FxHashMap`+`Vec` pair could be replaced by `FxIndexSet`, but #75278
1945 // found that to regress performance up to 2% in some cases. This might be
1946 // revisited after further improvements to `indexmap`.
1948 // This type is private to prevent accidentally constructing more than one
1949 // `Interner` on the same thread, which makes it easy to mix up `Symbol`s
1950 // between `Interner`s.
1952 struct InternerInner
{
1953 arena
: DroplessArena
,
1954 names
: FxHashMap
<&'
static str, Symbol
>,
1955 strings
: Vec
<&'
static str>,
1959 fn prefill(init
: &[&'
static str]) -> Self {
1960 Interner(Lock
::new(InternerInner
{
1961 strings
: init
.into(),
1962 names
: init
.iter().copied().zip((0..).map(Symbol
::new
)).collect(),
1963 ..Default
::default()
1968 fn intern(&self, string
: &str) -> Symbol
{
1969 let mut inner
= self.0.lock();
1970 if let Some(&name
) = inner
.names
.get(string
) {
1974 let name
= Symbol
::new(inner
.strings
.len() as u32);
1976 // SAFETY: we convert from `&str` to `&[u8]`, clone it into the arena,
1977 // and immediately convert the clone back to `&[u8], all because there
1978 // is no `inner.arena.alloc_str()` method. This is clearly safe.
1980 unsafe { str::from_utf8_unchecked(inner.arena.alloc_slice(string.as_bytes())) }
;
1982 // SAFETY: we can extend the arena allocation to `'static` because we
1983 // only access these while the arena is still alive.
1984 let string
: &'
static str = unsafe { &*(string as *const str) }
;
1985 inner
.strings
.push(string
);
1987 // This second hash table lookup can be avoided by using `RawEntryMut`,
1988 // but this code path isn't hot enough for it to be worth it. See
1989 // #91445 for details.
1990 inner
.names
.insert(string
, name
);
1994 // Get the symbol as a string. `Symbol::as_str()` should be used in
1995 // preference to this function.
1996 fn get(&self, symbol
: Symbol
) -> &str {
1997 self.0.lock().strings
[symbol
.0.as_usize()]
2001 // This module has a very short name because it's used a lot.
2002 /// This module contains all the defined keyword `Symbol`s.
2004 /// Given that `kw` is imported, use them like `kw::keyword_name`.
2005 /// For example `kw::Loop` or `kw::Break`.
2007 pub use super::kw_generated
::*;
2010 // This module has a very short name because it's used a lot.
2011 /// This module contains all the defined non-keyword `Symbol`s.
2013 /// Given that `sym` is imported, use them like `sym::symbol_name`.
2014 /// For example `sym::rustfmt` or `sym::u8`.
2017 use std
::convert
::TryInto
;
2020 pub use super::sym_generated
::*;
2022 // Used from a macro in `librustc_feature/accepted.rs`
2023 pub use super::kw
::MacroRules
as macro_rules
;
2025 /// Get the symbol for an integer.
2027 /// The first few non-negative integers each have a static symbol and therefore
2029 pub fn integer
<N
: TryInto
<usize> + Copy
+ ToString
>(n
: N
) -> Symbol
{
2030 if let Result
::Ok(idx
) = n
.try_into() {
2032 return Symbol
::new(super::SYMBOL_DIGITS_BASE
+ idx
as u32);
2035 Symbol
::intern(&n
.to_string())
2040 fn is_special(self) -> bool
{
2041 self <= kw
::Underscore
2044 fn is_used_keyword_always(self) -> bool
{
2045 self >= kw
::As
&& self <= kw
::While
2048 fn is_used_keyword_conditional(self, edition
: impl FnOnce() -> Edition
) -> bool
{
2049 (self >= kw
::Async
&& self <= kw
::Dyn
) && edition() >= Edition
::Edition2018
2052 fn is_unused_keyword_always(self) -> bool
{
2053 self >= kw
::Abstract
&& self <= kw
::Yield
2056 fn is_unused_keyword_conditional(self, edition
: impl FnOnce() -> Edition
) -> bool
{
2057 self == kw
::Try
&& edition() >= Edition
::Edition2018
2060 pub fn is_reserved(self, edition
: impl Copy
+ FnOnce() -> Edition
) -> bool
{
2062 || self.is_used_keyword_always()
2063 || self.is_unused_keyword_always()
2064 || self.is_used_keyword_conditional(edition
)
2065 || self.is_unused_keyword_conditional(edition
)
2068 /// A keyword or reserved identifier that can be used as a path segment.
2069 pub fn is_path_segment_keyword(self) -> bool
{
2071 || self == kw
::SelfLower
2072 || self == kw
::SelfUpper
2073 || self == kw
::Crate
2074 || self == kw
::PathRoot
2075 || self == kw
::DollarCrate
2078 /// Returns `true` if the symbol is `true` or `false`.
2079 pub fn is_bool_lit(self) -> bool
{
2080 self == kw
::True
|| self == kw
::False
2083 /// Returns `true` if this symbol can be a raw identifier.
2084 pub fn can_be_raw(self) -> bool
{
2085 self != kw
::Empty
&& self != kw
::Underscore
&& !self.is_path_segment_keyword()
2088 /// Is this symbol was interned in compiler's `symbols!` macro
2089 pub fn is_preinterned(self) -> bool
{
2090 self.as_u32() < PREINTERNED_SYMBOLS_COUNT
2095 // Returns `true` for reserved identifiers used internally for elided lifetimes,
2096 // unnamed method parameters, crate root module, error recovery etc.
2097 pub fn is_special(self) -> bool
{
2098 self.name
.is_special()
2101 /// Returns `true` if the token is a keyword used in the language.
2102 pub fn is_used_keyword(self) -> bool
{
2103 // Note: `span.edition()` is relatively expensive, don't call it unless necessary.
2104 self.name
.is_used_keyword_always()
2105 || self.name
.is_used_keyword_conditional(|| self.span
.edition())
2108 /// Returns `true` if the token is a keyword reserved for possible future use.
2109 pub fn is_unused_keyword(self) -> bool
{
2110 // Note: `span.edition()` is relatively expensive, don't call it unless necessary.
2111 self.name
.is_unused_keyword_always()
2112 || self.name
.is_unused_keyword_conditional(|| self.span
.edition())
2115 /// Returns `true` if the token is either a special identifier or a keyword.
2116 pub fn is_reserved(self) -> bool
{
2117 // Note: `span.edition()` is relatively expensive, don't call it unless necessary.
2118 self.name
.is_reserved(|| self.span
.edition())
2121 /// A keyword or reserved identifier that can be used as a path segment.
2122 pub fn is_path_segment_keyword(self) -> bool
{
2123 self.name
.is_path_segment_keyword()
2126 /// We see this identifier in a normal identifier position, like variable name or a type.
2127 /// How was it written originally? Did it use the raw form? Let's try to guess.
2128 pub fn is_raw_guess(self) -> bool
{
2129 self.name
.can_be_raw() && self.is_reserved()