Skip to content

Remove Ident::empty #140252

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 8 additions & 15 deletions compiler/rustc_hir/src/hir/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,21 +50,14 @@ fn trait_object_roundtrips() {
}

fn trait_object_roundtrips_impl(syntax: TraitObjectSyntax) {
let unambig = TyKind::TraitObject::<'_, ()>(
&[],
TaggedRef::new(
&const {
Lifetime {
hir_id: HirId::INVALID,
ident: Ident::new(sym::name, DUMMY_SP),
kind: LifetimeKind::Static,
source: LifetimeSource::Other,
syntax: LifetimeSyntax::Hidden,
}
},
syntax,
),
);
let lt = Lifetime {
hir_id: HirId::INVALID,
ident: Ident::new(sym::name, DUMMY_SP),
kind: LifetimeKind::Static,
source: LifetimeSource::Other,
syntax: LifetimeSyntax::Hidden,
};
let unambig = TyKind::TraitObject::<'_, ()>(&[], TaggedRef::new(&lt, syntax));
let unambig_to_ambig = unsafe { std::mem::transmute::<_, TyKind<'_, AmbigArg>>(unambig) };

match unambig_to_ambig {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3828,7 +3828,7 @@ impl<'a> Parser<'a> {
// Convert `label` -> `'label`,
// so that nameres doesn't complain about non-existing label
let label = format!("'{}", ident.name);
let ident = Ident { name: Symbol::intern(&label), span: ident.span };
let ident = Ident::new(Symbol::intern(&label), ident.span);

self.dcx().emit_err(errors::ExpectedLabelFoundIdent {
span: ident.span,
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_resolve/src/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
source = module_path.pop().unwrap();
if rename.is_none() {
// Keep the span of `self`, but the name of `foo`
ident = Ident { name: source.ident.name, span: self_span };
ident = Ident::new(source.ident.name, self_span);
}
}
} else {
Expand Down Expand Up @@ -597,7 +597,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
if let Some(crate_name) = crate_name {
// `crate_name` should not be interpreted as relative.
module_path.push(Segment::from_ident_and_id(
Ident { name: kw::PathRoot, span: source.ident.span },
Ident::new(kw::PathRoot, source.ident.span),
self.r.next_node_id(),
));
source.ident.name = crate_name;
Expand Down
25 changes: 18 additions & 7 deletions compiler/rustc_resolve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2157,13 +2157,24 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
ns: Namespace,
parent_scope: ParentScope<'ra>,
) -> Option<Res> {
let mut segments =
Vec::from_iter(path_str.split("::").map(Ident::from_str).map(Segment::from_ident));
if let Some(segment) = segments.first_mut() {
if segment.ident.name == kw::Empty {
segment.ident.name = kw::PathRoot;
}
}
let segments: Result<Vec<_>, ()> = path_str
.split("::")
.enumerate()
.map(|(i, s)| {
let sym = if s.is_empty() {
if i == 0 {
// For a path like `::a::b`, use `kw::PathRoot` as the leading segment.
kw::PathRoot
} else {
return Err(()); // occurs in cases like `String::`
}
} else {
Symbol::intern(s)
};
Ok(Segment::from_ident(Ident::with_dummy_span(sym)))
})
.collect();
let Ok(segments) = segments else { return None };

match self.maybe_resolve_path(&segments, Some(ns), &parent_scope, None) {
PathResult::Module(ModuleOrUniformRoot::Module(module)) => Some(module.res().unwrap()),
Expand Down
22 changes: 9 additions & 13 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2342,35 +2342,31 @@ pub const STDLIB_STABLE_CRATES: &[Symbol] = &[sym::std, sym::core, sym::alloc, s

#[derive(Copy, Clone, Eq, HashStable_Generic, Encodable, Decodable)]
pub struct Ident {
// `name` should never be the empty symbol. If you are considering that,
// you are probably conflating "empty identifer with "no identifier" and
// you should use `Option<Ident>` instead.
pub name: Symbol,
pub span: Span,
}

impl Ident {
#[inline]
/// Constructs a new identifier from a symbol and a span.
pub const fn new(name: Symbol, span: Span) -> Ident {
pub fn new(name: Symbol, span: Span) -> Ident {
assert_ne!(name, kw::Empty);
Ident { name, span }
}

/// Constructs a new identifier with a dummy span.
#[inline]
pub const fn with_dummy_span(name: Symbol) -> Ident {
pub fn with_dummy_span(name: Symbol) -> 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.
// present. Note that this does *not* use the empty symbol; `sym::dummy`
// makes it clear that it's intended as a dummy value, and is more likely
// to be detected if it accidentally does get used.
#[inline]
pub fn dummy() -> Ident {
Ident::with_dummy_span(sym::dummy)
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/clean/render_macro_matchers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ fn print_tts(printer: &mut Printer<'_>, tts: &TokenStream) {
}

fn usually_needs_space_between_keyword_and_open_delim(symbol: Symbol, span: Span) -> bool {
let ident = Ident { name: symbol, span };
let ident = Ident::new(symbol, span);
let is_keyword = ident.is_used_keyword() || ident.is_unused_keyword();
if !is_keyword {
// An identifier that is not a keyword usually does not need a space
Expand Down
21 changes: 15 additions & 6 deletions src/librustdoc/passes/collect_intra_doc_links.rs
Original file line number Diff line number Diff line change
Expand Up @@ -496,12 +496,21 @@ impl<'tcx> LinkCollector<'_, 'tcx> {

// Try looking for methods and associated items.
// NB: `path_root` could be empty when resolving in the root namespace (e.g. `::std`).
let (path_root, item_str) = path_str.rsplit_once("::").ok_or_else(|| {
// If there's no `::`, it's not an associated item.
// So we can be sure that `rustc_resolve` was accurate when it said it wasn't resolved.
debug!("found no `::`, assuming {path_str} was correctly not in scope");
UnresolvedPath { item_id, module_id, partial_res: None, unresolved: path_str.into() }
})?;
let (path_root, item_str) = match path_str.rsplit_once("::") {
Some(res @ (_path_root, item_str)) if !item_str.is_empty() => res,
_ => {
// If there's no `::`, or the `::` is at the end (e.g. `String::`) it's not an
// associated item. So we can be sure that `rustc_resolve` was accurate when it
// said it wasn't resolved.
debug!("`::` missing or at end, assuming {path_str} was not in scope");
return Err(UnresolvedPath {
item_id,
module_id,
partial_res: None,
unresolved: path_str.into(),
});
}
};
let item_name = Symbol::intern(item_str);

// FIXME(#83862): this arbitrarily gives precedence to primitives over modules to support
Expand Down
Loading