1
Fork 0

Replace infallible name_or_empty methods with fallible name methods.

I'm removing empty identifiers everywhere, because in practice they
always mean "no identifier" rather than "empty identifier". (An empty
identifier is impossible.) It's better to use `Option` to mean "no
identifier" because you then can't forget about the "no identifier"
possibility.

Some specifics:
- When testing an attribute for a single name, the commit uses the
  `has_name` method.
- When testing an attribute for multiple names, the commit uses the new
  `has_any_name` method.
- When using `match` on an attribute, the match arms now have `Some` on
  them.

In the tests, we now avoid printing empty identifiers by not printing
the identifier in the `error:` line at all, instead letting the carets
point out the problem.
This commit is contained in:
Nicholas Nethercote 2025-04-10 14:33:59 +10:00
parent 7e1f2f9c54
commit 2fef0a30ae
40 changed files with 217 additions and 203 deletions

View file

@ -305,8 +305,8 @@ impl MetaItem {
if let [PathSegment { ident, .. }] = self.path.segments[..] { Some(ident) } else { None }
}
pub fn name_or_empty(&self) -> Symbol {
self.ident().unwrap_or_else(Ident::empty).name
pub fn name(&self) -> Option<Symbol> {
self.ident().map(|ident| ident.name)
}
pub fn has_name(&self, name: Symbol) -> bool {
@ -511,13 +511,14 @@ impl MetaItemInner {
}
}
/// For a single-segment meta item, returns its name; otherwise, returns `None`.
/// For a single-segment meta item, returns its identifier; otherwise, returns `None`.
pub fn ident(&self) -> Option<Ident> {
self.meta_item().and_then(|meta_item| meta_item.ident())
}
pub fn name_or_empty(&self) -> Symbol {
self.ident().unwrap_or_else(Ident::empty).name
/// For a single-segment meta item, returns its name; otherwise, returns `None`.
pub fn name(&self) -> Option<Symbol> {
self.ident().map(|ident| ident.name)
}
/// Returns `true` if this list item is a MetaItem with a name of `name`.
@ -738,9 +739,9 @@ pub trait AttributeExt: Debug {
fn id(&self) -> AttrId;
/// For a single-segment attribute (i.e., `#[attr]` and not `#[path::atrr]`),
/// return the name of the attribute, else return the empty identifier.
fn name_or_empty(&self) -> Symbol {
self.ident().unwrap_or_else(Ident::empty).name
/// return the name of the attribute; otherwise, returns `None`.
fn name(&self) -> Option<Symbol> {
self.ident().map(|ident| ident.name)
}
/// Get the meta item list, `#[attr(meta item list)]`
@ -752,7 +753,7 @@ pub trait AttributeExt: Debug {
/// Gets the span of the value literal, as string, when using `#[attr = value]`
fn value_span(&self) -> Option<Span>;
/// For a single-segment attribute, returns its name; otherwise, returns `None`.
/// For a single-segment attribute, returns its ident; otherwise, returns `None`.
fn ident(&self) -> Option<Ident>;
/// Checks whether the path of this attribute matches the name.
@ -770,6 +771,11 @@ pub trait AttributeExt: Debug {
self.ident().map(|x| x.name == name).unwrap_or(false)
}
#[inline]
fn has_any_name(&self, names: &[Symbol]) -> bool {
names.iter().any(|&name| self.has_name(name))
}
/// get the span of the entire attribute
fn span(&self) -> Span;
@ -813,8 +819,8 @@ impl Attribute {
AttributeExt::id(self)
}
pub fn name_or_empty(&self) -> Symbol {
AttributeExt::name_or_empty(self)
pub fn name(&self) -> Option<Symbol> {
AttributeExt::name(self)
}
pub fn meta_item_list(&self) -> Option<ThinVec<MetaItemInner>> {
@ -846,6 +852,11 @@ impl Attribute {
AttributeExt::has_name(self, name)
}
#[inline]
pub fn has_any_name(&self, names: &[Symbol]) -> bool {
AttributeExt::has_any_name(self, names)
}
pub fn span(&self) -> Span {
AttributeExt::span(self)
}