about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNicholas Nethercote <n.nethercote@gmail.com>2025-03-04 17:10:55 +1100
committerNicholas Nethercote <n.nethercote@gmail.com>2025-03-12 09:35:11 +1100
commit0b2d7062c47fa385ff83e20dc53b13c8c5ba4616 (patch)
tree4bc279d596a743d5ea5d9defb03616783b67663d
parentfe04460f6fdc32c0783ca7cab6a0fb73ed254100 (diff)
downloadrust-0b2d7062c47fa385ff83e20dc53b13c8c5ba4616.tar.gz
rust-0b2d7062c47fa385ff83e20dc53b13c8c5ba4616.zip
Introduce `sym::dummy` and `Ident::dummy`.
The idea is to identify cases of symbols/identifiers that are not
expected to be used. There isn't a perfectly sharp line between "dummy"
and "not dummy", but I think it's useful nonetheless.
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs2
-rw-r--r--compiler/rustc_attr_parsing/src/context.rs3
-rw-r--r--compiler/rustc_attr_parsing/src/parser.rs4
-rw-r--r--compiler/rustc_expand/src/mbe/quoted.rs2
-rw-r--r--compiler/rustc_hir/src/hir.rs2
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs2
-rw-r--r--compiler/rustc_span/src/symbol.rs22
7 files changed, 29 insertions, 8 deletions
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index e4396a50a15..fc31912283a 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -1948,7 +1948,7 @@ impl DummyAstNode for Item {
                 span: Default::default(),
                 tokens: Default::default(),
             },
-            ident: Ident::empty(),
+            ident: Ident::dummy(),
             kind: ItemKind::ExternCrate(None),
             tokens: Default::default(),
         }
diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs
index 0e6b0bab082..35541bb04bd 100644
--- a/compiler/rustc_attr_parsing/src/context.rs
+++ b/compiler/rustc_attr_parsing/src/context.rs
@@ -9,7 +9,6 @@ use rustc_errors::{DiagCtxtHandle, Diagnostic};
 use rustc_feature::Features;
 use rustc_hir::{AttrArgs, AttrItem, AttrPath, Attribute, HashIgnoredAttrId};
 use rustc_session::Session;
-use rustc_span::symbol::kw;
 use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym};
 
 use crate::attributes::allow_unstable::{AllowConstFnUnstableParser, AllowInternalUnstableParser};
@@ -338,7 +337,7 @@ impl<'sess> AttributeParser<'sess> {
                         "expr in place where literal is expected (builtin attr parsing)",
                     );
                     ast::MetaItemLit {
-                        symbol: kw::Empty,
+                        symbol: sym::dummy,
                         suffix: None,
                         kind: ast::LitKind::Err(guar),
                         span: DUMMY_SP,
diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs
index f0cce26f4e2..a8a1460591c 100644
--- a/compiler/rustc_attr_parsing/src/parser.rs
+++ b/compiler/rustc_attr_parsing/src/parser.rs
@@ -12,7 +12,7 @@ use rustc_ast::{AttrArgs, DelimArgs, Expr, ExprKind, LitKind, MetaItemLit, Norma
 use rustc_ast_pretty::pprust;
 use rustc_errors::DiagCtxtHandle;
 use rustc_hir::{self as hir, AttrPath};
-use rustc_span::symbol::{Ident, kw};
+use rustc_span::symbol::{Ident, kw, sym};
 use rustc_span::{ErrorGuaranteed, Span, Symbol};
 
 pub struct SegmentIterator<'a> {
@@ -360,7 +360,7 @@ fn expr_to_lit(dcx: DiagCtxtHandle<'_>, expr: &Expr, span: Span) -> MetaItemLit
             span,
             "expr in place where literal is expected (builtin attr parsing)",
         );
-        MetaItemLit { symbol: kw::Empty, suffix: None, kind: LitKind::Err(guar), span }
+        MetaItemLit { symbol: sym::dummy, suffix: None, kind: LitKind::Err(guar), span }
     }
 }
 
diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs
index 8cb001391c5..0ea53627fe7 100644
--- a/compiler/rustc_expand/src/mbe/quoted.rs
+++ b/compiler/rustc_expand/src/mbe/quoted.rs
@@ -274,7 +274,7 @@ fn parse_tree<'a>(
                     let msg =
                         format!("expected identifier, found `{}`", pprust::token_to_string(token),);
                     sess.dcx().span_err(token.span, msg);
-                    TokenTree::MetaVar(token.span, Ident::empty())
+                    TokenTree::MetaVar(token.span, Ident::dummy())
                 }
 
                 // There are no more tokens. Just return the `$` we already have.
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 53f0194091c..4ec7aff7286 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -243,7 +243,7 @@ impl<'hir> PathSegment<'hir> {
     }
 
     pub fn invalid() -> Self {
-        Self::new(Ident::empty(), HirId::INVALID, Res::Err)
+        Self::new(Ident::dummy(), HirId::INVALID, Res::Err)
     }
 
     pub fn args(&self) -> &GenericArgs<'hir> {
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index e3405c89b79..88d1126de1a 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -2266,7 +2266,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                     && !first.ident.is_path_segment_keyword() =>
             {
                 // Insert a placeholder that's later replaced by `self`/`super`/etc.
-                path.insert(0, Segment::from_ident(Ident::empty()));
+                path.insert(0, Segment::from_ident(Ident::dummy()));
             }
             _ => return None,
         }
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 718f23d761f..8a8bec35d81 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -33,6 +33,15 @@ symbols! {
         // Special reserved identifiers used internally for elided lifetimes,
         // unnamed method parameters, crate root module, error recovery etc.
         // Matching predicates: `is_any_keyword`, `is_special`/`is_reserved`
+        //
+        // Notes about `kw::Empty`:
+        // - Its use can blur the lines between "empty symbol" and "no symbol".
+        //   Using `Option<Symbol>` is preferable, where possible, because that
+        //   is unambiguous.
+        // - For dummy symbols that are never used and absolutely must be
+        //   present, it's better to use `sym::dummy` than `kw::Empty`, because
+        //   it's clearer that it's intended as a dummy value, and more likely
+        //   to be detected if it accidentally does get used.
         Empty:              "",
         PathRoot:           "{{root}}",
         DollarCrate:        "$crate",
@@ -834,6 +843,7 @@ symbols! {
         drop_types_in_const,
         dropck_eyepatch,
         dropck_parametricity,
+        dummy: "<!dummy!>", // use this instead of `kw::Empty` for symbols that won't be used
         dummy_cgu_name,
         dylib,
         dyn_compatible_for_dispatch,
@@ -2305,11 +2315,23 @@ impl Ident {
         Ident::new(name, DUMMY_SP)
     }
 
+    /// This is best avoided, because it blurs the lines between "empty
+    /// identifier" and "no identifier". Using `Option<Ident>` is preferable,
+    /// where possible, because that is unambiguous.
     #[inline]
     pub fn empty() -> Ident {
         Ident::with_dummy_span(kw::Empty)
     }
 
+    // For dummy identifiers that are never used and absolutely must be
+    // present, it's better to use `Ident::dummy` than `Ident::Empty`, because
+    // it's clearer that it's intended as a dummy value, and more likely to be
+    // detected if it accidentally does get used.
+    #[inline]
+    pub fn dummy() -> Ident {
+        Ident::with_dummy_span(sym::dummy)
+    }
+
     /// Maps a string to an identifier with a dummy span.
     pub fn from_str(string: &str) -> Ident {
         Ident::with_dummy_span(Symbol::intern(string))