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_macros
::HashStable_Generic
;
9 use rustc_serialize
::{Decodable, Decoder, Encodable, Encoder}
;
11 use std
::cmp
::{Ord, PartialEq, PartialOrd}
;
13 use std
::hash
::{Hash, Hasher}
;
16 use crate::{Edition, Span, DUMMY_SP, SESSION_GLOBALS}
;
21 // The proc macro code for this is in `compiler/rustc_macros/src/symbols.rs`.
23 // After modifying this list adjust `is_special`, `is_used_keyword`/`is_unused_keyword`,
24 // this should be rarely necessary though if the keywords are kept in alphabetic order.
26 // Special reserved identifiers used internally for elided lifetimes,
27 // unnamed method parameters, crate root module, error recovery etc.
30 DollarCrate
: "$crate",
33 // Keywords that are used in stable Rust.
70 // Keywords that are used in unstable Rust or reserved for future use.
84 // Edition-specific keywords that are used in stable Rust.
85 Async
: "async", // >= 2018 Edition only
86 Await
: "await", // >= 2018 Edition only
87 Dyn
: "dyn", // >= 2018 Edition only
89 // Edition-specific keywords that are used in unstable Rust or reserved for future use.
90 Try
: "try", // >= 2018 Edition only
92 // Special lifetime names
93 UnderscoreLifetime
: "'_",
94 StaticLifetime
: "'static",
96 // Weak keywords, have special meaning only in specific contexts.
100 MacroRules
: "macro_rules",
105 // Pre-interned symbols that can be referred to with `rustc_span::sym::*`.
107 // The symbol is the stringified identifier unless otherwise specified, in
108 // which case the name should mention the non-identifier punctuation.
109 // E.g. `sym::proc_dash_macro` represents "proc-macro", and it shouldn't be
110 // called `sym::proc_macro` because then it's easy to mistakenly think it
111 // represents "proc_macro".
113 // As well as the symbols listed, there are symbols for the strings
114 // "0", "1", ..., "9", which are accessible via `sym::integer`.
116 // The proc macro will abort if symbols are not in alphabetical order (as
117 // defined by `impl Ord for str`) or if any symbols are duplicated. Vim
118 // users can sort the list by selecting it and executing the command
119 // `:'<,'>!LC_ALL=C sort`.
121 // There is currently no checking that all symbols are used; that would be
191 ProceduralMasqueradeDummyType
,
232 aarch64_target_feature
,
236 abi_c_cmse_nonsecure_call
,
238 abi_msp430_interrupt
,
251 advanced_slice_patterns
,
266 allow_internal_unsafe
,
267 allow_internal_unstable
,
273 arbitrary_enum_discriminant
,
274 arbitrary_self_types
,
286 assert_receiver_is_total_eq
,
290 associated_type_bounds
,
291 associated_type_defaults
,
302 augmented_assignments
,
304 automatically_derived
,
305 avx512_target_feature
,
311 bind_by_move_pattern_guards
,
322 borrowck_graphviz_format
,
323 borrowck_graphviz_postflow
,
324 borrowck_graphviz_preflow
,
328 braced_empty_structs
,
339 capture_disjoint_fields
,
352 cfg_target_has_atomic
,
353 cfg_target_thread_local
,
363 closure_to_fn_coercion
,
365 cmpxchg16b_target_feature
,
366 cmse_nonsecure_entry
,
374 conservative_impl_trait
,
377 const_compare_raw_pointers
,
380 const_evaluatable_checked
,
383 const_fn_floating_point_arithmetic
,
384 const_fn_fn_ptr_basics
,
388 const_generics_defaults
,
391 const_in_array_repeat_expressions
,
397 const_precise_live_drops
,
400 const_raw_ptr_to_usize_cast
,
403 const_trait_bound_opt_out
,
419 core_panic_2015_macro
,
428 crate_visibility_modifier
,
429 crt_dash_static
: "crt-static",
438 custom_inner_attributes
,
439 custom_test_frameworks
,
453 default_alloc_error_handler
,
454 default_lib_allocator
,
455 default_type_parameter_fallback
,
457 delay_span_bug_from_inside_query
,
465 destructuring_assignment
,
481 document_private_items
,
482 dotdot_in_tuple_patterns
,
483 dotdoteq_in_patterns
,
491 dropck_parametricity
,
500 emit_enum_variant_arg
,
508 ermsb_target_feature
,
513 exclusive_range_pattern
,
514 exhaustive_integer_patterns
,
525 extended_key_value_attributes
,
526 extern_absolute_paths
,
527 extern_crate_item_prelude
,
549 field_init_shorthand
,
554 float_to_int_unchecked
,
582 from_size_align_unchecked
,
595 generic_associated_types
,
602 half_open_range_patterns
,
606 hexagon_target_feature
,
608 homogeneous_aggregate
,
625 if_while_or_patterns
,
627 impl_header_lifetime_elision
,
630 impl_trait_in_bindings
,
636 inclusive_range_syntax
,
639 infer_outlives_requirements
,
640 infer_static_outlives_requirements
,
641 inherent_associated_types
,
653 irrefutable_let_patterns
,
657 issue_5723_bootstrap
,
658 issue_tracker_base_url
,
670 lazy_normalization_consts
,
682 link_llvm_intrinsics
,
701 macro_at_most_once_rep
,
702 macro_attributes_in_derive_output
,
705 macro_lifetime_matcher
,
706 macro_literal_matcher
,
718 match_beginning_vert
,
719 match_default_bindings
,
739 min_type_alias_impl_trait
,
747 movbe_target_feature
,
796 nontrapping_dash_fptoint
: "nontrapping-fptoint",
804 object_safe_for_dispatch
,
807 omit_gdb_pretty_printer_section
,
816 optin_builtin_traits
,
825 overlapping_marker_traits
,
835 panic_implementation
,
865 post_dash_lto
: "post-lto",
866 powerpc_target_feature
,
871 pre_dash_lto
: "pre-lto",
872 precise_pointer_size_matching
,
876 prefetch_read_instruction
,
878 prefetch_write_instruction
,
883 proc_dash_macro
: "proc-macro",
885 proc_macro_attribute
,
891 proc_macro_internals
,
893 proc_macro_non_items
,
894 proc_macro_path_invoc
,
907 quad_precision_float
,
914 re_rebalance_coherence
,
917 read_enum_variant_arg
,
925 reexport_test_harness_main
,
938 relaxed_struct_unsize
,
954 riscv_target_feature
,
970 rust_eh_catch_typeinfo
,
972 rust_eh_register_frames
,
973 rust_eh_unregister_frames
,
977 rustc_allocator_nounwind
,
978 rustc_allow_const_fn_unstable
,
979 rustc_args_required_const
,
982 rustc_capture_analysis
,
985 rustc_const_unstable
,
986 rustc_conversion_suggestion
,
989 rustc_diagnostic_item
,
990 rustc_diagnostic_macros
,
993 rustc_dump_env_program_clauses
,
994 rustc_dump_program_clauses
,
995 rustc_dump_user_substs
,
997 rustc_expected_cgu_reuse
,
998 rustc_if_this_changed
,
999 rustc_inherit_overflow_checks
,
1001 rustc_layout_scalar_valid_range_end
,
1002 rustc_layout_scalar_valid_range_start
,
1003 rustc_legacy_const_generics
,
1004 rustc_macro_transparency
,
1006 rustc_nonnull_optimization_guaranteed
,
1007 rustc_object_lifetime_default
,
1008 rustc_on_unimplemented
,
1011 rustc_partition_codegened
,
1012 rustc_partition_reused
,
1014 rustc_peek_definite_init
,
1015 rustc_peek_indirectly_mutable
,
1016 rustc_peek_liveness
,
1017 rustc_peek_maybe_init
,
1018 rustc_peek_maybe_uninit
,
1019 rustc_polymorphize_error
,
1021 rustc_proc_macro_decls
,
1024 rustc_reservation_impl
,
1026 rustc_specialization_trait
,
1028 rustc_std_internal_symbol
,
1032 rustc_then_this_would_need
,
1033 rustc_unsafe_specialization_marker
,
1037 rvalue_static_promotion
,
1086 simd_reduce_add_ordered
,
1087 simd_reduce_add_unordered
,
1092 simd_reduce_max_nanless
,
1094 simd_reduce_min_nanless
,
1095 simd_reduce_mul_ordered
,
1096 simd_reduce_mul_unordered
,
1100 simd_saturating_add
,
1101 simd_saturating_sub
,
1104 simd_select_bitmask
,
1131 sse4a_target_feature
,
1143 std_panic_2015_macro
,
1146 stmt_expr_attributes
,
1147 stop_after_dataflow
,
1152 struct_field_attributes
,
1174 target_has_atomic_equal_alignment
,
1175 target_has_atomic_load_store
,
1177 target_pointer_width
,
1178 target_target_vendor
,
1179 target_thread_local
,
1185 termination_trait_test
,
1188 test_accepted_feature
,
1190 test_removed_feature
,
1217 type_alias_enum_variants
,
1218 type_alias_impl_trait
,
1229 unaligned_volatile_load
,
1230 unaligned_volatile_store
,
1239 underscore_const_names
,
1241 underscore_lifetimes
,
1244 universal_impl_trait
,
1251 unrestricted_attribute_tokens
,
1252 unsafe_block_in_unsafe_fn
,
1254 unsafe_no_drop_flag
,
1258 unsized_tuple_coercion
,
1261 unused_qualifications
,
1284 visible_private_types
,
1286 volatile_copy_memory
,
1287 volatile_copy_nonoverlapping_memory
,
1289 volatile_set_memory
,
1295 wasm_target_feature
,
1310 #[derive(Copy, Clone, Eq, HashStable_Generic, Encodable, Decodable)]
1318 /// Constructs a new identifier from a symbol and a span.
1319 pub const fn new(name
: Symbol
, span
: Span
) -> Ident
{
1320 Ident { name, span }
1323 /// Constructs a new identifier with a dummy span.
1325 pub const fn with_dummy_span(name
: Symbol
) -> Ident
{
1326 Ident
::new(name
, DUMMY_SP
)
1330 pub fn invalid() -> Ident
{
1331 Ident
::with_dummy_span(kw
::Empty
)
1334 /// Maps a string to an identifier with a dummy span.
1335 pub fn from_str(string
: &str) -> Ident
{
1336 Ident
::with_dummy_span(Symbol
::intern(string
))
1339 /// Maps a string and a span to an identifier.
1340 pub fn from_str_and_span(string
: &str, span
: Span
) -> Ident
{
1341 Ident
::new(Symbol
::intern(string
), span
)
1344 /// Replaces `lo` and `hi` with those from `span`, but keep hygiene context.
1345 pub fn with_span_pos(self, span
: Span
) -> Ident
{
1346 Ident
::new(self.name
, span
.with_ctxt(self.span
.ctxt()))
1349 pub fn without_first_quote(self) -> Ident
{
1350 Ident
::new(Symbol
::intern(self.as_str().trim_start_matches('
\''
)), self.span
)
1353 /// "Normalize" ident for use in comparisons using "item hygiene".
1354 /// Identifiers with same string value become same if they came from the same macro 2.0 macro
1355 /// (e.g., `macro` item, but not `macro_rules` item) and stay different if they came from
1356 /// different macro 2.0 macros.
1357 /// Technically, this operation strips all non-opaque marks from ident's syntactic context.
1358 pub fn normalize_to_macros_2_0(self) -> Ident
{
1359 Ident
::new(self.name
, self.span
.normalize_to_macros_2_0())
1362 /// "Normalize" ident for use in comparisons using "local variable hygiene".
1363 /// Identifiers with same string value become same if they came from the same non-transparent
1364 /// macro (e.g., `macro` or `macro_rules!` items) and stay different if they came from different
1365 /// non-transparent macros.
1366 /// Technically, this operation strips all transparent marks from ident's syntactic context.
1367 pub fn normalize_to_macro_rules(self) -> Ident
{
1368 Ident
::new(self.name
, self.span
.normalize_to_macro_rules())
1371 /// Convert the name to a `SymbolStr`. This is a slowish operation because
1372 /// it requires locking the symbol interner.
1373 pub fn as_str(self) -> SymbolStr
{
1378 impl PartialEq
for Ident
{
1379 fn eq(&self, rhs
: &Self) -> bool
{
1380 self.name
== rhs
.name
&& self.span
.ctxt() == rhs
.span
.ctxt()
1384 impl Hash
for Ident
{
1385 fn hash
<H
: Hasher
>(&self, state
: &mut H
) {
1386 self.name
.hash(state
);
1387 self.span
.ctxt().hash(state
);
1391 impl fmt
::Debug
for Ident
{
1392 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
1393 fmt
::Display
::fmt(self, f
)?
;
1394 fmt
::Debug
::fmt(&self.span
.ctxt(), f
)
1398 /// This implementation is supposed to be used in error messages, so it's expected to be identical
1399 /// to printing the original identifier token written in source code (`token_to_string`),
1400 /// except that AST identifiers don't keep the rawness flag, so we have to guess it.
1401 impl fmt
::Display
for Ident
{
1402 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
1403 fmt
::Display
::fmt(&IdentPrinter
::new(self.name
, self.is_raw_guess(), None
), f
)
1407 /// This is the most general way to print identifiers.
1408 /// AST pretty-printer is used as a fallback for turning AST structures into token streams for
1409 /// proc macros. Additionally, proc macros may stringify their input and expect it survive the
1410 /// stringification (especially true for proc macro derives written between Rust 1.15 and 1.30).
1411 /// So we need to somehow pretty-print `$crate` in a way preserving at least some of its
1412 /// hygiene data, most importantly name of the crate it refers to.
1413 /// As a result we print `$crate` as `crate` if it refers to the local crate
1414 /// and as `::other_crate_name` if it refers to some other crate.
1415 /// Note, that this is only done if the ident token is printed from inside of AST pretty-pringing,
1416 /// but not otherwise. Pretty-printing is the only way for proc macros to discover token contents,
1417 /// so we should not perform this lossy conversion if the top level call to the pretty-printer was
1418 /// done for a token stream or a single token.
1419 pub struct IdentPrinter
{
1422 /// Span used for retrieving the crate name to which `$crate` refers to,
1423 /// if this field is `None` then the `$crate` conversion doesn't happen.
1424 convert_dollar_crate
: Option
<Span
>,
1428 /// The most general `IdentPrinter` constructor. Do not use this.
1429 pub fn new(symbol
: Symbol
, is_raw
: bool
, convert_dollar_crate
: Option
<Span
>) -> IdentPrinter
{
1430 IdentPrinter { symbol, is_raw, convert_dollar_crate }
1433 /// This implementation is supposed to be used when printing identifiers
1434 /// as a part of pretty-printing for larger AST pieces.
1435 /// Do not use this either.
1436 pub fn for_ast_ident(ident
: Ident
, is_raw
: bool
) -> IdentPrinter
{
1437 IdentPrinter
::new(ident
.name
, is_raw
, Some(ident
.span
))
1441 impl fmt
::Display
for IdentPrinter
{
1442 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
1445 } else if self.symbol
== kw
::DollarCrate
{
1446 if let Some(span
) = self.convert_dollar_crate
{
1447 let converted
= span
.ctxt().dollar_crate_name();
1448 if !converted
.is_path_segment_keyword() {
1451 return fmt
::Display
::fmt(&converted
, f
);
1454 fmt
::Display
::fmt(&self.symbol
, f
)
1458 /// An newtype around `Ident` that calls [Ident::normalize_to_macro_rules] on
1460 // FIXME(matthewj, petrochenkov) Use this more often, add a similar
1461 // `ModernIdent` struct and use that as well.
1462 #[derive(Copy, Clone, Eq, PartialEq, Hash)]
1463 pub struct MacroRulesNormalizedIdent(Ident
);
1465 impl MacroRulesNormalizedIdent
{
1466 pub fn new(ident
: Ident
) -> Self {
1467 Self(ident
.normalize_to_macro_rules())
1471 impl fmt
::Debug
for MacroRulesNormalizedIdent
{
1472 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
1473 fmt
::Debug
::fmt(&self.0, f
)
1477 impl fmt
::Display
for MacroRulesNormalizedIdent
{
1478 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
1479 fmt
::Display
::fmt(&self.0, f
)
1483 /// An interned string.
1485 /// Internally, a `Symbol` is implemented as an index, and all operations
1486 /// (including hashing, equality, and ordering) operate on that index. The use
1487 /// of `rustc_index::newtype_index!` means that `Option<Symbol>` only takes up 4 bytes,
1488 /// because `rustc_index::newtype_index!` reserves the last 256 values for tagging purposes.
1490 /// Note that `Symbol` cannot directly be a `rustc_index::newtype_index!` because it
1491 /// implements `fmt::Debug`, `Encodable`, and `Decodable` in special ways.
1492 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
1493 pub struct Symbol(SymbolIndex
);
1495 rustc_index
::newtype_index
! {
1496 pub struct SymbolIndex { .. }
1500 const fn new(n
: u32) -> Self {
1501 Symbol(SymbolIndex
::from_u32(n
))
1504 /// Maps a string to its interned representation.
1505 pub fn intern(string
: &str) -> Self {
1506 with_interner(|interner
| interner
.intern(string
))
1509 /// Convert to a `SymbolStr`. This is a slowish operation because it
1510 /// requires locking the symbol interner.
1511 pub fn as_str(self) -> SymbolStr
{
1512 with_interner(|interner
| unsafe {
1513 SymbolStr { string: std::mem::transmute::<&str, &str>(interner.get(self)) }
1517 pub fn as_u32(self) -> u32 {
1521 pub fn is_empty(self) -> bool
{
1525 /// This method is supposed to be used in error messages, so it's expected to be
1526 /// identical to printing the original identifier token written in source code
1527 /// (`token_to_string`, `Ident::to_string`), except that symbols don't keep the rawness flag
1528 /// or edition, so we have to guess the rawness using the global edition.
1529 pub fn to_ident_string(self) -> String
{
1530 Ident
::with_dummy_span(self).to_string()
1534 impl fmt
::Debug
for Symbol
{
1535 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
1536 fmt
::Debug
::fmt(&self.as_str(), f
)
1540 impl fmt
::Display
for Symbol
{
1541 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
1542 fmt
::Display
::fmt(&self.as_str(), f
)
1546 impl<S
: Encoder
> Encodable
<S
> for Symbol
{
1547 fn encode(&self, s
: &mut S
) -> Result
<(), S
::Error
> {
1548 s
.emit_str(&self.as_str())
1552 impl<D
: Decoder
> Decodable
<D
> for Symbol
{
1554 fn decode(d
: &mut D
) -> Result
<Symbol
, D
::Error
> {
1555 Ok(Symbol
::intern(&d
.read_str()?
))
1559 impl<CTX
> HashStable
<CTX
> for Symbol
{
1561 fn hash_stable(&self, hcx
: &mut CTX
, hasher
: &mut StableHasher
) {
1562 self.as_str().hash_stable(hcx
, hasher
);
1566 impl<CTX
> ToStableHashKey
<CTX
> for Symbol
{
1567 type KeyType
= SymbolStr
;
1570 fn to_stable_hash_key(&self, _
: &CTX
) -> SymbolStr
{
1575 // The `&'static str`s in this type actually point into the arena.
1577 // The `FxHashMap`+`Vec` pair could be replaced by `FxIndexSet`, but #75278
1578 // found that to regress performance up to 2% in some cases. This might be
1579 // revisited after further improvements to `indexmap`.
1581 pub struct Interner
{
1582 arena
: DroplessArena
,
1583 names
: FxHashMap
<&'
static str, Symbol
>,
1584 strings
: Vec
<&'
static str>,
1588 fn prefill(init
: &[&'
static str]) -> Self {
1590 strings
: init
.into(),
1591 names
: init
.iter().copied().zip((0..).map(Symbol
::new
)).collect(),
1592 ..Default
::default()
1597 pub fn intern(&mut self, string
: &str) -> Symbol
{
1598 if let Some(&name
) = self.names
.get(string
) {
1602 let name
= Symbol
::new(self.strings
.len() as u32);
1604 // `from_utf8_unchecked` is safe since we just allocated a `&str` which is known to be
1607 unsafe { str::from_utf8_unchecked(self.arena.alloc_slice(string.as_bytes())) }
;
1608 // It is safe to extend the arena allocation to `'static` because we only access
1609 // these while the arena is still alive.
1610 let string
: &'
static str = unsafe { &*(string as *const str) }
;
1611 self.strings
.push(string
);
1612 self.names
.insert(string
, name
);
1616 // Get the symbol as a string. `Symbol::as_str()` should be used in
1617 // preference to this function.
1618 pub fn get(&self, symbol
: Symbol
) -> &str {
1619 self.strings
[symbol
.0.as_usize()]
1623 // This module has a very short name because it's used a lot.
1624 /// This module contains all the defined keyword `Symbol`s.
1626 /// Given that `kw` is imported, use them like `kw::keyword_name`.
1627 /// For example `kw::Loop` or `kw::Break`.
1629 pub use super::kw_generated
::*;
1632 // This module has a very short name because it's used a lot.
1633 /// This module contains all the defined non-keyword `Symbol`s.
1635 /// Given that `sym` is imported, use them like `sym::symbol_name`.
1636 /// For example `sym::rustfmt` or `sym::u8`.
1639 use std
::convert
::TryInto
;
1642 pub use super::sym_generated
::*;
1644 // Used from a macro in `librustc_feature/accepted.rs`
1645 pub use super::kw
::MacroRules
as macro_rules
;
1647 /// Get the symbol for an integer.
1649 /// The first few non-negative integers each have a static symbol and therefore
1651 pub fn integer
<N
: TryInto
<usize> + Copy
+ ToString
>(n
: N
) -> Symbol
{
1652 if let Result
::Ok(idx
) = n
.try_into() {
1654 return Symbol
::new(super::SYMBOL_DIGITS_BASE
+ idx
as u32);
1657 Symbol
::intern(&n
.to_string())
1662 fn is_special(self) -> bool
{
1663 self <= kw
::Underscore
1666 fn is_used_keyword_always(self) -> bool
{
1667 self >= kw
::As
&& self <= kw
::While
1670 fn is_used_keyword_conditional(self, edition
: impl FnOnce() -> Edition
) -> bool
{
1671 (self >= kw
::Async
&& self <= kw
::Dyn
) && edition() >= Edition
::Edition2018
1674 fn is_unused_keyword_always(self) -> bool
{
1675 self >= kw
::Abstract
&& self <= kw
::Yield
1678 fn is_unused_keyword_conditional(self, edition
: impl FnOnce() -> Edition
) -> bool
{
1679 self == kw
::Try
&& edition() >= Edition
::Edition2018
1682 pub fn is_reserved(self, edition
: impl Copy
+ FnOnce() -> Edition
) -> bool
{
1684 || self.is_used_keyword_always()
1685 || self.is_unused_keyword_always()
1686 || self.is_used_keyword_conditional(edition
)
1687 || self.is_unused_keyword_conditional(edition
)
1690 /// A keyword or reserved identifier that can be used as a path segment.
1691 pub fn is_path_segment_keyword(self) -> bool
{
1693 || self == kw
::SelfLower
1694 || self == kw
::SelfUpper
1695 || self == kw
::Crate
1696 || self == kw
::PathRoot
1697 || self == kw
::DollarCrate
1700 /// Returns `true` if the symbol is `true` or `false`.
1701 pub fn is_bool_lit(self) -> bool
{
1702 self == kw
::True
|| self == kw
::False
1705 /// Returns `true` if this symbol can be a raw identifier.
1706 pub fn can_be_raw(self) -> bool
{
1707 self != kw
::Empty
&& self != kw
::Underscore
&& !self.is_path_segment_keyword()
1712 // Returns `true` for reserved identifiers used internally for elided lifetimes,
1713 // unnamed method parameters, crate root module, error recovery etc.
1714 pub fn is_special(self) -> bool
{
1715 self.name
.is_special()
1718 /// Returns `true` if the token is a keyword used in the language.
1719 pub fn is_used_keyword(self) -> bool
{
1720 // Note: `span.edition()` is relatively expensive, don't call it unless necessary.
1721 self.name
.is_used_keyword_always()
1722 || self.name
.is_used_keyword_conditional(|| self.span
.edition())
1725 /// Returns `true` if the token is a keyword reserved for possible future use.
1726 pub fn is_unused_keyword(self) -> bool
{
1727 // Note: `span.edition()` is relatively expensive, don't call it unless necessary.
1728 self.name
.is_unused_keyword_always()
1729 || self.name
.is_unused_keyword_conditional(|| self.span
.edition())
1732 /// Returns `true` if the token is either a special identifier or a keyword.
1733 pub fn is_reserved(self) -> bool
{
1734 // Note: `span.edition()` is relatively expensive, don't call it unless necessary.
1735 self.name
.is_reserved(|| self.span
.edition())
1738 /// A keyword or reserved identifier that can be used as a path segment.
1739 pub fn is_path_segment_keyword(self) -> bool
{
1740 self.name
.is_path_segment_keyword()
1743 /// We see this identifier in a normal identifier position, like variable name or a type.
1744 /// How was it written originally? Did it use the raw form? Let's try to guess.
1745 pub fn is_raw_guess(self) -> bool
{
1746 self.name
.can_be_raw() && self.is_reserved()
1751 fn with_interner
<T
, F
: FnOnce(&mut Interner
) -> T
>(f
: F
) -> T
{
1752 SESSION_GLOBALS
.with(|session_globals
| f(&mut *session_globals
.symbol_interner
.lock()))
1755 /// An alternative to [`Symbol`], useful when the chars within the symbol need to
1756 /// be accessed. It deliberately has limited functionality and should only be
1757 /// used for temporary values.
1759 /// Because the interner outlives any thread which uses this type, we can
1760 /// safely treat `string` which points to interner data, as an immortal string,
1761 /// as long as this type never crosses between threads.
1763 // FIXME: ensure that the interner outlives any thread which uses `SymbolStr`,
1764 // by creating a new thread right after constructing the interner.
1765 #[derive(Clone, Eq, PartialOrd, Ord)]
1766 pub struct SymbolStr
{
1767 string
: &'
static str,
1770 // This impl allows a `SymbolStr` to be directly equated with a `String` or
1772 impl<T
: std
::ops
::Deref
<Target
= str>> std
::cmp
::PartialEq
<T
> for SymbolStr
{
1773 fn eq(&self, other
: &T
) -> bool
{
1774 self.string
== other
.deref()
1778 impl !Send
for SymbolStr {}
1779 impl !Sync
for SymbolStr {}
1781 /// This impl means that if `ss` is a `SymbolStr`:
1782 /// - `*ss` is a `str`;
1783 /// - `&*ss` is a `&str` (and `match &*ss { ... }` is a common pattern).
1784 /// - `&ss as &str` is a `&str`, which means that `&ss` can be passed to a
1785 /// function expecting a `&str`.
1786 impl std
::ops
::Deref
for SymbolStr
{
1789 fn deref(&self) -> &str {
1794 impl fmt
::Debug
for SymbolStr
{
1795 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
1796 fmt
::Debug
::fmt(self.string
, f
)
1800 impl fmt
::Display
for SymbolStr
{
1801 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
1802 fmt
::Display
::fmt(self.string
, f
)
1806 impl<CTX
> HashStable
<CTX
> for SymbolStr
{
1808 fn hash_stable(&self, hcx
: &mut CTX
, hasher
: &mut StableHasher
) {
1809 self.string
.hash_stable(hcx
, hasher
)
1813 impl<CTX
> ToStableHashKey
<CTX
> for SymbolStr
{
1814 type KeyType
= SymbolStr
;
1817 fn to_stable_hash_key(&self, _
: &CTX
) -> SymbolStr
{