]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_span/symbol.rs
Auto merge of #69474 - Dylan-DPC:rollup-ciotplu, r=Dylan-DPC
[rust.git] / src / librustc_span / symbol.rs
index 1cc4a27788098e6f54ede20880154705aec51d55..b8e5ea97f4e4792f1d6ae642dc8b9d0e56dfb986 100644 (file)
@@ -97,6 +97,7 @@
         Auto:               "auto",
         Catch:              "catch",
         Default:            "default",
+        MacroRules:         "macro_rules",
         Raw:                "raw",
         Union:              "union",
     }
         macro_lifetime_matcher,
         macro_literal_matcher,
         macro_reexport,
-        macro_rules,
         macros_in_extern,
         macro_use,
         macro_vis_matcher,
@@ -893,19 +893,17 @@ fn hash<H: Hasher>(&self, state: &mut H) {
 
 impl fmt::Debug for Ident {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        if self.is_raw_guess() {
-            write!(f, "r#")?;
-        }
-        write!(f, "{}{:?}", self.name, self.span.ctxt())
+        fmt::Display::fmt(self, f)?;
+        fmt::Debug::fmt(&self.span.ctxt(), f)
     }
 }
 
+/// This implementation 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`),
+/// except that AST identifiers don't keep the rawness flag, so we have to guess it.
 impl fmt::Display for Ident {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        if self.is_raw_guess() {
-            write!(f, "r#")?;
-        }
-        fmt::Display::fmt(&self.name, f)
+        fmt::Display::fmt(&IdentPrinter::new(self.name, self.is_raw_guess(), None), f)
     }
 }
 
@@ -929,6 +927,59 @@ fn default_decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
     }
 }
 
+/// This is the most general way to print identifiers.
+/// AST pretty-printer is used as a fallback for turning AST structures into token streams for
+/// proc macros. Additionally, proc macros may stringify their input and expect it survive the
+/// stringification (especially true for proc macro derives written between Rust 1.15 and 1.30).
+/// So we need to somehow pretty-print `$crate` in a way preserving at least some of its
+/// hygiene data, most importantly name of the crate it refers to.
+/// As a result we print `$crate` as `crate` if it refers to the local crate
+/// and as `::other_crate_name` if it refers to some other crate.
+/// Note, that this is only done if the ident token is printed from inside of AST pretty-pringing,
+/// but not otherwise. Pretty-printing is the only way for proc macros to discover token contents,
+/// so we should not perform this lossy conversion if the top level call to the pretty-printer was
+/// done for a token stream or a single token.
+pub struct IdentPrinter {
+    symbol: Symbol,
+    is_raw: bool,
+    /// Span used for retrieving the crate name to which `$crate` refers to,
+    /// if this field is `None` then the `$crate` conversion doesn't happen.
+    convert_dollar_crate: Option<Span>,
+}
+
+impl IdentPrinter {
+    /// The most general `IdentPrinter` constructor. Do not use this.
+    pub fn new(symbol: Symbol, is_raw: bool, convert_dollar_crate: Option<Span>) -> IdentPrinter {
+        IdentPrinter { symbol, is_raw, convert_dollar_crate }
+    }
+
+    /// This implementation is supposed to be used when printing identifiers
+    /// as a part of pretty-printing for larger AST pieces.
+    /// Do not use this either.
+    pub fn for_ast_ident(ident: Ident, is_raw: bool) -> IdentPrinter {
+        IdentPrinter::new(ident.name, is_raw, Some(ident.span))
+    }
+}
+
+impl fmt::Display for IdentPrinter {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        if self.is_raw {
+            f.write_str("r#")?;
+        } else {
+            if self.symbol == kw::DollarCrate {
+                if let Some(span) = self.convert_dollar_crate {
+                    let converted = span.ctxt().dollar_crate_name();
+                    if !converted.is_path_segment_keyword() {
+                        f.write_str("::")?;
+                    }
+                    return fmt::Display::fmt(&converted, f);
+                }
+            }
+        }
+        fmt::Display::fmt(&self.symbol, f)
+    }
+}
+
 /// An interned string.
 ///
 /// Internally, a `Symbol` is implemented as an index, and all operations
@@ -993,6 +1044,7 @@ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
 }
 
 impl Decodable for Symbol {
+    #[inline]
     fn decode<D: Decoder>(d: &mut D) -> Result<Symbol, D::Error> {
         Ok(Symbol::intern(&d.read_str()?))
     }
@@ -1031,6 +1083,7 @@ fn prefill(init: &[&'static str]) -> Self {
         }
     }
 
+    #[inline]
     pub fn intern(&mut self, string: &str) -> Symbol {
         if let Some(&name) = self.names.get(string) {
             return name;
@@ -1071,6 +1124,9 @@ pub mod sym {
 
     symbols!();
 
+    // 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.
     pub fn integer<N: TryInto<usize> + Copy + ToString>(n: N) -> Symbol {