1
Fork 0

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.
This commit is contained in:
Nicholas Nethercote 2025-03-04 17:10:55 +11:00
parent fe04460f6f
commit 0b2d7062c4
7 changed files with 29 additions and 8 deletions

View file

@ -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(),
}

View file

@ -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,

View file

@ -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 }
}
}

View file

@ -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.

View file

@ -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> {

View file

@ -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,
}

View file

@ -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))