about summary refs log tree commit diff
path: root/compiler/rustc_span
diff options
context:
space:
mode:
authorCorey Farwell <coreyf@rwell.org>2020-12-31 23:27:33 -0500
committerCorey Farwell <coreyf@rwell.org>2020-12-31 23:27:33 -0500
commitd482de30ea70d537dced8ec04a3903e3264cf106 (patch)
tree67d6cd380ef7a66e785a54993bb0ca93b07b43ec /compiler/rustc_span
parent26cc060756d0456b17fdc53ac5d34e7f7bdc873d (diff)
parent99ad5a1a2824fea1ecf60068fd3636beae7ea2da (diff)
downloadrust-d482de30ea70d537dced8ec04a3903e3264cf106.tar.gz
rust-d482de30ea70d537dced8ec04a3903e3264cf106.zip
Merge remote-tracking branch 'origin/master' into frewsxcv-san
Diffstat (limited to 'compiler/rustc_span')
-rw-r--r--compiler/rustc_span/src/edition.rs19
-rw-r--r--compiler/rustc_span/src/hygiene.rs4
-rw-r--r--compiler/rustc_span/src/lev_distance.rs16
-rw-r--r--compiler/rustc_span/src/lib.rs68
-rw-r--r--compiler/rustc_span/src/source_map.rs8
-rw-r--r--compiler/rustc_span/src/span_encoding.rs8
-rw-r--r--compiler/rustc_span/src/symbol.rs111
7 files changed, 152 insertions, 82 deletions
diff --git a/compiler/rustc_span/src/edition.rs b/compiler/rustc_span/src/edition.rs
index 4d0c92f51d7..efbb0a23a6f 100644
--- a/compiler/rustc_span/src/edition.rs
+++ b/compiler/rustc_span/src/edition.rs
@@ -4,24 +4,25 @@ use std::str::FromStr;
 
 use rustc_macros::HashStable_Generic;
 
-/// The edition of the compiler (RFC 2052)
+/// The edition of the compiler. (See [RFC 2052](https://github.com/rust-lang/rfcs/blob/master/text/2052-epochs.md).)
 #[derive(Clone, Copy, Hash, PartialEq, PartialOrd, Debug, Encodable, Decodable, Eq)]
 #[derive(HashStable_Generic)]
 pub enum Edition {
-    // editions must be kept in order, oldest to newest
+    // When adding new editions, be sure to do the following:
+    //
+    // - update the `ALL_EDITIONS` const
+    // - update the `EDITION_NAME_LIST` const
+    // - add a `rust_####()` function to the session
+    // - update the enum in Cargo's sources as well
+    //
+    // Editions *must* be kept in order, oldest to newest.
     /// The 2015 edition
     Edition2015,
     /// The 2018 edition
     Edition2018,
-    // when adding new editions, be sure to update:
-    //
-    // - Update the `ALL_EDITIONS` const
-    // - Update the EDITION_NAME_LIST const
-    // - add a `rust_####()` function to the session
-    // - update the enum in Cargo's sources as well
 }
 
-// must be in order from oldest to newest
+// Must be in order from oldest to newest.
 pub const ALL_EDITIONS: &[Edition] = &[Edition::Edition2015, Edition::Edition2018];
 
 pub const EDITION_NAME_LIST: &str = "2015|2018";
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index 0f82db1d05a..fdc0d225bb8 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -1065,7 +1065,7 @@ pub fn decode_syntax_context<
             parent: SyntaxContext::root(),
             opaque: SyntaxContext::root(),
             opaque_and_semitransparent: SyntaxContext::root(),
-            dollar_crate_name: kw::Invalid,
+            dollar_crate_name: kw::Empty,
         });
         let mut ctxts = outer_ctxts.lock();
         let new_len = raw_id as usize + 1;
@@ -1092,7 +1092,7 @@ pub fn decode_syntax_context<
             ctxt_data,
         );
         // Make sure nothing weird happening while `decode_data` was running
-        assert_eq!(dummy.dollar_crate_name, kw::Invalid);
+        assert_eq!(dummy.dollar_crate_name, kw::Empty);
     });
 
     Ok(new_ctxt)
diff --git a/compiler/rustc_span/src/lev_distance.rs b/compiler/rustc_span/src/lev_distance.rs
index edc6625a6ea..cea7871923b 100644
--- a/compiler/rustc_span/src/lev_distance.rs
+++ b/compiler/rustc_span/src/lev_distance.rs
@@ -1,10 +1,16 @@
+//! Levenshtein distances.
+//!
+//! The [Levenshtein distance] is a metric for measuring the difference between two strings.
+//!
+//! [Levenshtein distance]: https://en.wikipedia.org/wiki/Levenshtein_distance
+
 use crate::symbol::Symbol;
 use std::cmp;
 
 #[cfg(test)]
 mod tests;
 
-/// Finds the Levenshtein distance between two strings
+/// Finds the Levenshtein distance between two strings.
 pub fn lev_distance(a: &str, b: &str) -> usize {
     // cases which don't require further computation
     if a.is_empty() {
@@ -35,14 +41,14 @@ pub fn lev_distance(a: &str, b: &str) -> usize {
     dcol[t_last + 1]
 }
 
-/// Finds the best match for a given word in the given iterator
+/// Finds the best match for a given word in the given iterator.
 ///
 /// As a loose rule to avoid the obviously incorrect suggestions, it takes
 /// an optional limit for the maximum allowable edit distance, which defaults
 /// to one-third of the given word.
 ///
-/// Besides Levenshtein, we use case insensitive comparison to improve accuracy on an edge case with
-/// a lower(upper)case letters mismatch.
+/// Besides Levenshtein, we use case insensitive comparison to improve accuracy
+/// on an edge case with a lower(upper)case letters mismatch.
 #[cold]
 pub fn find_best_match_for_name(
     name_vec: &[Symbol],
@@ -98,7 +104,7 @@ fn find_match_by_sorted_words(iter_names: &[Symbol], lookup: &str) -> Option<Sym
 
 fn sort_by_words(name: &str) -> String {
     let mut split_words: Vec<&str> = name.split('_').collect();
-    // We are sorting primitive &strs and can use unstable sort here
+    // We are sorting primitive &strs and can use unstable sort here.
     split_words.sort_unstable();
     split_words.join("_")
 }
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index f63a73acbf4..80095307175 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -1,4 +1,13 @@
-//! The source positions and related helper functions.
+//! Source positions and related helper functions.
+//!
+//! Important concepts in this module include:
+//!
+//! - the *span*, represented by [`SpanData`] and related types;
+//! - source code as represented by a [`SourceMap`]; and
+//! - interned strings, represented by [`Symbol`]s, with some common symbols available statically in the [`sym`] module.
+//!
+//! Unlike most compilers, the span contains not only the position in the source code, but also various other metadata,
+//! such as the edition and macro hygiene. This metadata is stored in [`SyntaxContext`] and [`ExpnData`].
 //!
 //! ## Note
 //!
@@ -124,7 +133,7 @@ pub enum RealFileName {
 
 impl RealFileName {
     /// Returns the path suitable for reading from the file system on the local host.
-    /// Avoid embedding this in build artifacts; see `stable_name` for that.
+    /// Avoid embedding this in build artifacts; see `stable_name()` for that.
     pub fn local_path(&self) -> &Path {
         match self {
             RealFileName::Named(p)
@@ -133,7 +142,7 @@ impl RealFileName {
     }
 
     /// Returns the path suitable for reading from the file system on the local host.
-    /// Avoid embedding this in build artifacts; see `stable_name` for that.
+    /// Avoid embedding this in build artifacts; see `stable_name()` for that.
     pub fn into_local_path(self) -> PathBuf {
         match self {
             RealFileName::Named(p)
@@ -143,7 +152,7 @@ impl RealFileName {
 
     /// Returns the path suitable for embedding into build artifacts. Note that
     /// a virtualized path will not correspond to a valid file system path; see
-    /// `local_path` for something that is more likely to return paths into the
+    /// `local_path()` for something that is more likely to return paths into the
     /// local host file system.
     pub fn stable_name(&self) -> &Path {
         match self {
@@ -173,7 +182,7 @@ pub enum FileName {
     /// Custom sources for explicit parser calls from plugins and drivers.
     Custom(String),
     DocTest(PathBuf, isize),
-    /// Post-substitution inline assembly from LLVM
+    /// Post-substitution inline assembly from LLVM.
     InlineAsm(u64),
 }
 
@@ -182,7 +191,7 @@ impl std::fmt::Display for FileName {
         use FileName::*;
         match *self {
             Real(RealFileName::Named(ref path)) => write!(fmt, "{}", path.display()),
-            // FIXME: might be nice to display both compoments of Devirtualized.
+            // FIXME: might be nice to display both components of Devirtualized.
             // But for now (to backport fix for issue #70924), best to not
             // perturb diagnostics so its obvious test suite still works.
             Real(RealFileName::Devirtualized { ref local_path, virtual_name: _ }) => {
@@ -266,14 +275,17 @@ impl FileName {
     }
 }
 
+/// Represents a span.
+///
 /// Spans represent a region of code, used for error reporting. Positions in spans
-/// are *absolute* positions from the beginning of the source_map, not positions
-/// relative to `SourceFile`s. Methods on the `SourceMap` can be used to relate spans back
+/// are *absolute* positions from the beginning of the [`SourceMap`], not positions
+/// relative to [`SourceFile`]s. Methods on the `SourceMap` can be used to relate spans back
 /// to the original source.
-/// You must be careful if the span crosses more than one file - you will not be
+///
+/// You must be careful if the span crosses more than one file, since you will not be
 /// able to use many of the functions on spans in source_map and you cannot assume
-/// that the length of the `span = hi - lo`; there may be space in the `BytePos`
-/// range between files.
+/// that the length of the span is equal to `span.hi - span.lo`; there may be space in the
+/// [`BytePos`] range between files.
 ///
 /// `SpanData` is public because `Span` uses a thread-local interner and can't be
 /// sent to other threads, but some pieces of performance infra run in a separate thread.
@@ -384,7 +396,7 @@ impl Span {
         Span::new(lo, hi, SyntaxContext::root())
     }
 
-    /// Returns a new span representing an empty span at the beginning of this span
+    /// Returns a new span representing an empty span at the beginning of this span.
     #[inline]
     pub fn shrink_to_lo(self) -> Span {
         let span = self.data();
@@ -398,7 +410,7 @@ impl Span {
     }
 
     #[inline]
-    /// Returns true if hi == lo
+    /// Returns `true` if `hi == lo`.
     pub fn is_empty(&self) -> bool {
         let span = self.data();
         span.hi == span.lo
@@ -512,7 +524,7 @@ impl Span {
     }
 
     /// Checks if a span is "internal" to a macro in which `unsafe`
-    /// can be used without triggering the `unsafe_code` lint
+    /// can be used without triggering the `unsafe_code` lint.
     //  (that is, a macro marked with `#[allow_internal_unsafe]`).
     pub fn allows_unsafe(&self) -> bool {
         self.ctxt().outer_expn_data().allow_internal_unsafe
@@ -700,6 +712,7 @@ impl Span {
     }
 }
 
+/// A span together with some additional data.
 #[derive(Clone, Debug)]
 pub struct SpanLabel {
     /// The span we are going to include in the final snippet.
@@ -743,7 +756,7 @@ impl<D: Decoder> Decodable<D> for Span {
 /// any spans that are debug-printed during the closure's execution.
 ///
 /// Normally, the global `TyCtxt` is used to retrieve the `SourceMap`
-/// (see `rustc_interface::callbacks::span_debug1). However, some parts
+/// (see `rustc_interface::callbacks::span_debug1`). However, some parts
 /// of the compiler (e.g. `rustc_parse`) may debug-print `Span`s before
 /// a `TyCtxt` is available. In this case, we fall back to
 /// the `SourceMap` provided to this function. If that is not available,
@@ -994,9 +1007,9 @@ pub enum ExternalSource {
     Unneeded,
     Foreign {
         kind: ExternalSourceKind,
-        /// This SourceFile's byte-offset within the source_map of its original crate
+        /// This SourceFile's byte-offset within the source_map of its original crate.
         original_start_pos: BytePos,
-        /// The end of this SourceFile within the source_map of its original crate
+        /// The end of this SourceFile within the source_map of its original crate.
         original_end_pos: BytePos,
     },
 }
@@ -1099,7 +1112,7 @@ impl SourceFileHash {
     }
 }
 
-/// A single source in the `SourceMap`.
+/// A single source in the [`SourceMap`].
 #[derive(Clone)]
 pub struct SourceFile {
     /// The name of the file that the source came from. Source that doesn't
@@ -1580,7 +1593,7 @@ fn remove_bom(src: &mut String, normalized_pos: &mut Vec<NormalizedPos>) {
 
 /// Replaces `\r\n` with `\n` in-place in `src`.
 ///
-/// Returns error if there's a lone `\r` in the string
+/// Returns error if there's a lone `\r` in the string.
 fn normalize_newlines(src: &mut String, normalized_pos: &mut Vec<NormalizedPos>) {
     if !src.as_bytes().contains(&b'\r') {
         return;
@@ -1705,13 +1718,16 @@ macro_rules! impl_pos {
 }
 
 impl_pos! {
-    /// A byte offset. Keep this small (currently 32-bits), as AST contains
-    /// a lot of them.
+    /// A byte offset.
+    ///
+    /// Keep this small (currently 32-bits), as AST contains a lot of them.
     #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
     pub struct BytePos(pub u32);
 
-    /// A character offset. Because of multibyte UTF-8 characters, a byte offset
-    /// is not equivalent to a character offset. The `SourceMap` will convert `BytePos`
+    /// A character offset.
+    ///
+    /// Because of multibyte UTF-8 characters, a byte offset
+    /// is not equivalent to a character offset. The [`SourceMap`] will convert [`BytePos`]
     /// values to `CharPos` values as necessary.
     #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
     pub struct CharPos(pub usize);
@@ -1835,8 +1851,9 @@ fn lookup_line(lines: &[BytePos], pos: BytePos) -> isize {
 }
 
 /// Requirements for a `StableHashingContext` to be used in this crate.
-/// This is a hack to allow using the `HashStable_Generic` derive macro
-/// instead of implementing everything in librustc_middle.
+///
+/// This is a hack to allow using the [`HashStable_Generic`] derive macro
+/// instead of implementing everything in rustc_middle.
 pub trait HashStableContext {
     fn hash_def_id(&mut self, _: DefId, hasher: &mut StableHasher);
     fn hash_crate_num(&mut self, _: CrateNum, hasher: &mut StableHasher);
@@ -1856,6 +1873,7 @@ where
     /// offsets into the `SourceMap`). Instead, we hash the (file name, line, column)
     /// triple, which stays the same even if the containing `SourceFile` has moved
     /// within the `SourceMap`.
+    ///
     /// Also note that we are hashing byte offsets for the column, not unicode
     /// codepoint offsets. For the purpose of the hash that's sufficient.
     /// Also, hashing filenames is expensive so we avoid doing it twice when the
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index e9b4eb6e4ab..fefc0cb48dd 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -1,9 +1,11 @@
-//! The `SourceMap` tracks all the source code used within a single crate, mapping
+//! Types for tracking pieces of source code within a crate.
+//!
+//! The [`SourceMap`] tracks all the source code used within a single crate, mapping
 //! from integer byte positions to the original source code location. Each bit
 //! of source parsed during crate parsing (typically files, in-memory strings,
 //! or various bits of macro expansion) cover a continuous range of bytes in the
-//! `SourceMap` and are represented by `SourceFile`s. Byte positions are stored in
-//! `Span` and used pervasively in the compiler. They are absolute positions
+//! `SourceMap` and are represented by [`SourceFile`]s. Byte positions are stored in
+//! [`Span`] and used pervasively in the compiler. They are absolute positions
 //! within the `SourceMap`, which upon request can be converted to line and column
 //! information, source code snippets, etc.
 
diff --git a/compiler/rustc_span/src/span_encoding.rs b/compiler/rustc_span/src/span_encoding.rs
index b05e01d666b..ceb9b59b13a 100644
--- a/compiler/rustc_span/src/span_encoding.rs
+++ b/compiler/rustc_span/src/span_encoding.rs
@@ -12,7 +12,7 @@ use rustc_data_structures::fx::FxIndexSet;
 
 /// A compressed span.
 ///
-/// `SpanData` is 12 bytes, which is a bit too big to stick everywhere. `Span`
+/// Whereas [`SpanData`] is 12 bytes, which is a bit too big to stick everywhere, `Span`
 /// is a form that only takes up 8 bytes, with less space for the length and
 /// context. The vast majority (99.9%+) of `SpanData` instances will fit within
 /// those 8 bytes; any `SpanData` whose fields don't fit into a `Span` are
@@ -42,13 +42,11 @@ use rustc_data_structures::fx::FxIndexSet;
 /// - `base` is 32 bits in both `Span` and `SpanData`, which means that `base`
 ///   values never cause interning. The number of bits needed for `base`
 ///   depends on the crate size. 32 bits allows up to 4 GiB of code in a crate.
-///   `script-servo` is the largest crate in `rustc-perf`, requiring 26 bits
-///   for some spans.
 /// - `len` is 15 bits in `Span` (a u16, minus 1 bit for the tag) and 32 bits
 ///   in `SpanData`, which means that large `len` values will cause interning.
 ///   The number of bits needed for `len` does not depend on the crate size.
-///   The most common number of bits for `len` are 0--7, with a peak usually at
-///   3 or 4, and then it drops off quickly from 8 onwards. 15 bits is enough
+///   The most common numbers of bits for `len` are from 0 to 7, with a peak usually
+///   at 3 or 4, and then it drops off quickly from 8 onwards. 15 bits is enough
 ///   for 99.99%+ of cases, but larger values (sometimes 20+ bits) might occur
 ///   dozens of times in a typical crate.
 /// - `ctxt` is 16 bits in `Span` and 32 bits in `SpanData`, which means that
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index b9c942d61a9..382b7a4f2db 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -13,7 +13,7 @@ use std::fmt;
 use std::hash::{Hash, Hasher};
 use std::str;
 
-use crate::{Span, DUMMY_SP, SESSION_GLOBALS};
+use crate::{Edition, Span, DUMMY_SP, SESSION_GLOBALS};
 
 #[cfg(test)]
 mod tests;
@@ -25,7 +25,7 @@ symbols! {
     Keywords {
         // Special reserved identifiers used internally for elided lifetimes,
         // unnamed method parameters, crate root module, error recovery etc.
-        Invalid:            "",
+        Empty:              "",
         PathRoot:           "{{root}}",
         DollarCrate:        "$crate",
         Underscore:         "_",
@@ -460,6 +460,9 @@ symbols! {
         document_private_items,
         dotdot_in_tuple_patterns,
         dotdoteq_in_patterns,
+        dreg,
+        dreg_low16,
+        dreg_low8,
         drop,
         drop_in_place,
         drop_types_in_const,
@@ -467,6 +470,7 @@ symbols! {
         dropck_parametricity,
         dylib,
         dyn_trait,
+        edition_macro_pats,
         eh_catch_typeinfo,
         eh_personality,
         emit_enum,
@@ -544,6 +548,7 @@ symbols! {
         format_args_capture,
         format_args_nl,
         freeze,
+        freg,
         frem_fast,
         from,
         from_desugaring,
@@ -627,6 +632,7 @@ symbols! {
         iter,
         keyword,
         kind,
+        kreg,
         label,
         label_break_value,
         lang,
@@ -652,6 +658,7 @@ symbols! {
         lint_reasons,
         literal,
         llvm_asm,
+        local,
         local_inner_macros,
         log10f32,
         log10f64,
@@ -802,6 +809,8 @@ symbols! {
         partial_ord,
         passes,
         pat,
+        pat2018,
+        pat2021,
         path,
         pattern_parentheses,
         phantom_data,
@@ -854,6 +863,9 @@ symbols! {
         pub_restricted,
         pure,
         pushpop_unsafe,
+        qreg,
+        qreg_low4,
+        qreg_low8,
         quad_precision_float,
         question_mark,
         quote,
@@ -875,6 +887,13 @@ symbols! {
         reexport_test_harness_main,
         reference,
         reflect,
+        reg,
+        reg16,
+        reg32,
+        reg64,
+        reg_abcd,
+        reg_byte,
+        reg_thumb,
         register_attr,
         register_tool,
         relaxed_adts,
@@ -1060,6 +1079,8 @@ symbols! {
         spotlight,
         sqrtf32,
         sqrtf64,
+        sreg,
+        sreg_low16,
         sse4a_target_feature,
         stable,
         staged_api,
@@ -1215,6 +1236,8 @@ symbols! {
         volatile_load,
         volatile_set_memory,
         volatile_store,
+        vreg,
+        vreg_low16,
         warn,
         wasm_import_module,
         wasm_target_feature,
@@ -1226,6 +1249,9 @@ symbols! {
         wrapping_mul,
         wrapping_sub,
         write_bytes,
+        xmm_reg,
+        ymm_reg,
+        zmm_reg,
     }
 }
 
@@ -1250,7 +1276,7 @@ impl Ident {
 
     #[inline]
     pub fn invalid() -> Ident {
-        Ident::with_dummy_span(kw::Invalid)
+        Ident::with_dummy_span(kw::Empty)
     }
 
     /// Maps a string to an identifier with a dummy span.
@@ -1428,12 +1454,6 @@ impl Symbol {
         with_interner(|interner| interner.intern(string))
     }
 
-    /// Access the symbol's chars. This is a slowish operation because it
-    /// requires locking the symbol interner.
-    pub fn with<F: FnOnce(&str) -> R, R>(self, f: F) -> R {
-        with_interner(|interner| f(interner.get(self)))
-    }
-
     /// Convert to a `SymbolStr`. This is a slowish operation because it
     /// requires locking the symbol interner.
     pub fn as_str(self) -> SymbolStr {
@@ -1446,6 +1466,10 @@ impl Symbol {
         self.0.as_u32()
     }
 
+    pub fn is_empty(self) -> bool {
+        self == kw::Empty
+    }
+
     /// This method is supposed to be used in error messages, so it's expected to be
     /// identical to printing the original identifier token written in source code
     /// (`token_to_string`, `Ident::to_string`), except that symbols don't keep the rawness flag
@@ -1457,19 +1481,19 @@ impl Symbol {
 
 impl fmt::Debug for Symbol {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.with(|str| fmt::Debug::fmt(&str, f))
+        fmt::Debug::fmt(&self.as_str(), f)
     }
 }
 
 impl fmt::Display for Symbol {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.with(|str| fmt::Display::fmt(&str, f))
+        fmt::Display::fmt(&self.as_str(), f)
     }
 }
 
 impl<S: Encoder> Encodable<S> for Symbol {
     fn encode(&self, s: &mut S) -> Result<(), S::Error> {
-        self.with(|string| s.emit_str(string))
+        s.emit_str(&self.as_str())
     }
 }
 
@@ -1550,8 +1574,7 @@ impl Interner {
 /// Given that `kw` is imported, use them like `kw::keyword_name`.
 /// For example `kw::Loop` or `kw::Break`.
 pub mod kw {
-    use super::Symbol;
-    keywords!();
+    pub use super::kw_generated::*;
 }
 
 // This module has a very short name because it's used a lot.
@@ -1559,22 +1582,23 @@ pub mod kw {
 ///
 /// Given that `sym` is imported, use them like `sym::symbol_name`.
 /// For example `sym::rustfmt` or `sym::u8`.
-#[allow(rustc::default_hash_types)]
 pub mod sym {
     use super::Symbol;
     use std::convert::TryInto;
 
-    define_symbols!();
+    pub use super::sym_generated::*;
 
     // Used from a macro in `librustc_feature/accepted.rs`
     pub use super::kw::MacroRules as macro_rules;
 
-    // Get the symbol for an integer. The first few non-negative integers each
-    // have a static symbol and therefore are fast.
+    /// Get the symbol for an integer.
+    ///
+    /// The first few non-negative integers each have a static symbol and therefore
+    /// are fast.
     pub fn integer<N: TryInto<usize> + Copy + ToString>(n: N) -> Symbol {
         if let Result::Ok(idx) = n.try_into() {
-            if let Option::Some(&sym_) = digits_array.get(idx) {
-                return sym_;
+            if idx < 10 {
+                return Symbol::new(super::SYMBOL_DIGITS_BASE + idx as u32);
             }
         }
         Symbol::intern(&n.to_string())
@@ -1582,12 +1606,32 @@ pub mod sym {
 }
 
 impl Symbol {
-    fn is_used_keyword_2018(self) -> bool {
-        self >= kw::Async && self <= kw::Dyn
+    fn is_special(self) -> bool {
+        self <= kw::Underscore
+    }
+
+    fn is_used_keyword_always(self) -> bool {
+        self >= kw::As && self <= kw::While
     }
 
-    fn is_unused_keyword_2018(self) -> bool {
-        self == kw::Try
+    fn is_used_keyword_conditional(self, edition: impl FnOnce() -> Edition) -> bool {
+        (self >= kw::Async && self <= kw::Dyn) && edition() >= Edition::Edition2018
+    }
+
+    fn is_unused_keyword_always(self) -> bool {
+        self >= kw::Abstract && self <= kw::Yield
+    }
+
+    fn is_unused_keyword_conditional(self, edition: impl FnOnce() -> Edition) -> bool {
+        self == kw::Try && edition() >= Edition::Edition2018
+    }
+
+    pub fn is_reserved(self, edition: impl Copy + FnOnce() -> Edition) -> bool {
+        self.is_special()
+            || self.is_used_keyword_always()
+            || self.is_unused_keyword_always()
+            || self.is_used_keyword_conditional(edition)
+            || self.is_unused_keyword_conditional(edition)
     }
 
     /// A keyword or reserved identifier that can be used as a path segment.
@@ -1605,9 +1649,9 @@ impl Symbol {
         self == kw::True || self == kw::False
     }
 
-    /// This symbol can be a raw identifier.
+    /// Returns `true` if this symbol can be a raw identifier.
     pub fn can_be_raw(self) -> bool {
-        self != kw::Invalid && self != kw::Underscore && !self.is_path_segment_keyword()
+        self != kw::Empty && self != kw::Underscore && !self.is_path_segment_keyword()
     }
 }
 
@@ -1615,26 +1659,27 @@ impl Ident {
     // Returns `true` for reserved identifiers used internally for elided lifetimes,
     // unnamed method parameters, crate root module, error recovery etc.
     pub fn is_special(self) -> bool {
-        self.name <= kw::Underscore
+        self.name.is_special()
     }
 
     /// Returns `true` if the token is a keyword used in the language.
     pub fn is_used_keyword(self) -> bool {
         // Note: `span.edition()` is relatively expensive, don't call it unless necessary.
-        self.name >= kw::As && self.name <= kw::While
-            || self.name.is_used_keyword_2018() && self.span.rust_2018()
+        self.name.is_used_keyword_always()
+            || self.name.is_used_keyword_conditional(|| self.span.edition())
     }
 
     /// Returns `true` if the token is a keyword reserved for possible future use.
     pub fn is_unused_keyword(self) -> bool {
         // Note: `span.edition()` is relatively expensive, don't call it unless necessary.
-        self.name >= kw::Abstract && self.name <= kw::Yield
-            || self.name.is_unused_keyword_2018() && self.span.rust_2018()
+        self.name.is_unused_keyword_always()
+            || self.name.is_unused_keyword_conditional(|| self.span.edition())
     }
 
     /// Returns `true` if the token is either a special identifier or a keyword.
     pub fn is_reserved(self) -> bool {
-        self.is_special() || self.is_used_keyword() || self.is_unused_keyword()
+        // Note: `span.edition()` is relatively expensive, don't call it unless necessary.
+        self.name.is_reserved(|| self.span.edition())
     }
 
     /// A keyword or reserved identifier that can be used as a path segment.
@@ -1654,7 +1699,7 @@ fn with_interner<T, F: FnOnce(&mut Interner) -> T>(f: F) -> T {
     SESSION_GLOBALS.with(|session_globals| f(&mut *session_globals.symbol_interner.lock()))
 }
 
-/// An alternative to `Symbol`, useful when the chars within the symbol need to
+/// An alternative to [`Symbol`], useful when the chars within the symbol need to
 /// be accessed. It deliberately has limited functionality and should only be
 /// used for temporary values.
 ///