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:
parent
7e1f2f9c54
commit
2fef0a30ae
40 changed files with 217 additions and 203 deletions
|
@ -404,7 +404,7 @@ passes_invalid_attr_at_crate_level =
|
|||
passes_invalid_attr_at_crate_level_item =
|
||||
the inner attribute doesn't annotate this {$kind}
|
||||
|
||||
passes_invalid_macro_export_arguments = `{$name}` isn't a valid `#[macro_export]` argument
|
||||
passes_invalid_macro_export_arguments = invalid `#[macro_export]` argument
|
||||
|
||||
passes_invalid_macro_export_arguments_too_many_items = `#[macro_export]` can only take 1 or 0 arguments
|
||||
|
||||
|
@ -771,8 +771,8 @@ passes_unreachable_due_to_uninhabited = unreachable {$descr}
|
|||
.label_orig = any code following this expression is unreachable
|
||||
.note = this expression has type `{$ty}`, which is uninhabited
|
||||
|
||||
passes_unrecognized_field =
|
||||
unrecognized field name `{$name}`
|
||||
passes_unrecognized_argument =
|
||||
unrecognized argument
|
||||
|
||||
passes_unstable_attr_for_already_stable_feature =
|
||||
can't mark as unstable using an already stable feature
|
||||
|
|
|
@ -9,7 +9,7 @@ use rustc_span::sym;
|
|||
use rustc_target::callconv::FnAbi;
|
||||
|
||||
use super::layout_test::ensure_wf;
|
||||
use crate::errors::{AbiInvalidAttribute, AbiNe, AbiOf, UnrecognizedField};
|
||||
use crate::errors::{AbiInvalidAttribute, AbiNe, AbiOf, UnrecognizedArgument};
|
||||
|
||||
pub fn test_abi(tcx: TyCtxt<'_>) {
|
||||
if !tcx.features().rustc_attrs() {
|
||||
|
@ -77,8 +77,8 @@ fn dump_abi_of_fn_item(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut
|
|||
// The `..` are the names of fields to dump.
|
||||
let meta_items = attr.meta_item_list().unwrap_or_default();
|
||||
for meta_item in meta_items {
|
||||
match meta_item.name_or_empty() {
|
||||
sym::debug => {
|
||||
match meta_item.name() {
|
||||
Some(sym::debug) => {
|
||||
let fn_name = tcx.item_name(item_def_id.into());
|
||||
tcx.dcx().emit_err(AbiOf {
|
||||
span: tcx.def_span(item_def_id),
|
||||
|
@ -88,8 +88,8 @@ fn dump_abi_of_fn_item(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut
|
|||
});
|
||||
}
|
||||
|
||||
name => {
|
||||
tcx.dcx().emit_err(UnrecognizedField { span: meta_item.span(), name });
|
||||
_ => {
|
||||
tcx.dcx().emit_err(UnrecognizedArgument { span: meta_item.span() });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -118,8 +118,8 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut
|
|||
}
|
||||
let meta_items = attr.meta_item_list().unwrap_or_default();
|
||||
for meta_item in meta_items {
|
||||
match meta_item.name_or_empty() {
|
||||
sym::debug => {
|
||||
match meta_item.name() {
|
||||
Some(sym::debug) => {
|
||||
let ty::FnPtr(sig_tys, hdr) = ty.kind() else {
|
||||
span_bug!(
|
||||
meta_item.span(),
|
||||
|
@ -138,7 +138,7 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut
|
|||
let fn_name = tcx.item_name(item_def_id.into());
|
||||
tcx.dcx().emit_err(AbiOf { span, fn_name, fn_abi: format!("{:#?}", abi) });
|
||||
}
|
||||
sym::assert_eq => {
|
||||
Some(sym::assert_eq) => {
|
||||
let ty::Tuple(fields) = ty.kind() else {
|
||||
span_bug!(
|
||||
meta_item.span(),
|
||||
|
@ -188,8 +188,8 @@ fn dump_abi_of_fn_type(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribut
|
|||
});
|
||||
}
|
||||
}
|
||||
name => {
|
||||
tcx.dcx().emit_err(UnrecognizedField { span: meta_item.span(), name });
|
||||
_ => {
|
||||
tcx.dcx().emit_err(UnrecognizedArgument { span: meta_item.span() });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -523,9 +523,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
fn check_no_sanitize(&self, attr: &Attribute, span: Span, target: Target) {
|
||||
if let Some(list) = attr.meta_item_list() {
|
||||
for item in list.iter() {
|
||||
let sym = item.name_or_empty();
|
||||
let sym = item.name();
|
||||
match sym {
|
||||
sym::address | sym::hwaddress => {
|
||||
Some(s @ sym::address | s @ sym::hwaddress) => {
|
||||
let is_valid =
|
||||
matches!(target, Target::Fn | Target::Method(..) | Target::Static);
|
||||
if !is_valid {
|
||||
|
@ -533,7 +533,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
attr_span: item.span(),
|
||||
defn_span: span,
|
||||
accepted_kind: "a function or static",
|
||||
attr_str: sym.as_str(),
|
||||
attr_str: s.as_str(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -544,7 +544,10 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
attr_span: item.span(),
|
||||
defn_span: span,
|
||||
accepted_kind: "a function",
|
||||
attr_str: sym.as_str(),
|
||||
attr_str: &match sym {
|
||||
Some(name) => name.to_string(),
|
||||
None => "...".to_string(),
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -592,7 +595,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
// * `#[track_caller]`
|
||||
// * `#[test]`, `#[ignore]`, `#[should_panic]`
|
||||
//
|
||||
// NOTE: when making changes to this list, check that `error_codes/E0736.md` remains accurate
|
||||
// NOTE: when making changes to this list, check that `error_codes/E0736.md` remains
|
||||
// accurate.
|
||||
const ALLOW_LIST: &[rustc_span::Symbol] = &[
|
||||
// conditional compilation
|
||||
sym::cfg_trace,
|
||||
|
@ -675,11 +679,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
if !ALLOW_LIST.iter().any(|name| other_attr.has_name(*name)) {
|
||||
if !other_attr.has_any_name(ALLOW_LIST) {
|
||||
self.dcx().emit_err(errors::NakedFunctionIncompatibleAttribute {
|
||||
span: other_attr.span(),
|
||||
naked_span: attr.span(),
|
||||
attr: other_attr.name_or_empty(),
|
||||
attr: other_attr.name().unwrap(),
|
||||
});
|
||||
|
||||
return;
|
||||
|
@ -1153,7 +1157,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
) {
|
||||
match target {
|
||||
Target::Use | Target::ExternCrate => {
|
||||
let do_inline = meta.name_or_empty() == sym::inline;
|
||||
let do_inline = meta.has_name(sym::inline);
|
||||
if let Some((prev_inline, prev_span)) = *specified_inline {
|
||||
if do_inline != prev_inline {
|
||||
let mut spans = MultiSpan::from_spans(vec![prev_span, meta.span()]);
|
||||
|
@ -1263,8 +1267,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
fn check_test_attr(&self, meta: &MetaItemInner, hir_id: HirId) {
|
||||
if let Some(metas) = meta.meta_item_list() {
|
||||
for i_meta in metas {
|
||||
match (i_meta.name_or_empty(), i_meta.meta_item()) {
|
||||
(sym::attr | sym::no_crate_inject, _) => {}
|
||||
match (i_meta.name(), i_meta.meta_item()) {
|
||||
(Some(sym::attr | sym::no_crate_inject), _) => {}
|
||||
(_, Some(m)) => {
|
||||
self.tcx.emit_node_span_lint(
|
||||
INVALID_DOC_ATTRIBUTES,
|
||||
|
@ -1325,61 +1329,63 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
if let Some(list) = attr.meta_item_list() {
|
||||
for meta in &list {
|
||||
if let Some(i_meta) = meta.meta_item() {
|
||||
match i_meta.name_or_empty() {
|
||||
sym::alias => {
|
||||
match i_meta.name() {
|
||||
Some(sym::alias) => {
|
||||
if self.check_attr_not_crate_level(meta, hir_id, "alias") {
|
||||
self.check_doc_alias(meta, hir_id, target, aliases);
|
||||
}
|
||||
}
|
||||
|
||||
sym::keyword => {
|
||||
Some(sym::keyword) => {
|
||||
if self.check_attr_not_crate_level(meta, hir_id, "keyword") {
|
||||
self.check_doc_keyword(meta, hir_id);
|
||||
}
|
||||
}
|
||||
|
||||
sym::fake_variadic => {
|
||||
Some(sym::fake_variadic) => {
|
||||
if self.check_attr_not_crate_level(meta, hir_id, "fake_variadic") {
|
||||
self.check_doc_fake_variadic(meta, hir_id);
|
||||
}
|
||||
}
|
||||
|
||||
sym::search_unbox => {
|
||||
Some(sym::search_unbox) => {
|
||||
if self.check_attr_not_crate_level(meta, hir_id, "fake_variadic") {
|
||||
self.check_doc_search_unbox(meta, hir_id);
|
||||
}
|
||||
}
|
||||
|
||||
sym::test => {
|
||||
Some(sym::test) => {
|
||||
if self.check_attr_crate_level(attr, meta, hir_id) {
|
||||
self.check_test_attr(meta, hir_id);
|
||||
}
|
||||
}
|
||||
|
||||
sym::html_favicon_url
|
||||
| sym::html_logo_url
|
||||
| sym::html_playground_url
|
||||
| sym::issue_tracker_base_url
|
||||
| sym::html_root_url
|
||||
| sym::html_no_source => {
|
||||
Some(
|
||||
sym::html_favicon_url
|
||||
| sym::html_logo_url
|
||||
| sym::html_playground_url
|
||||
| sym::issue_tracker_base_url
|
||||
| sym::html_root_url
|
||||
| sym::html_no_source,
|
||||
) => {
|
||||
self.check_attr_crate_level(attr, meta, hir_id);
|
||||
}
|
||||
|
||||
sym::cfg_hide => {
|
||||
Some(sym::cfg_hide) => {
|
||||
if self.check_attr_crate_level(attr, meta, hir_id) {
|
||||
self.check_doc_cfg_hide(meta, hir_id);
|
||||
}
|
||||
}
|
||||
|
||||
sym::inline | sym::no_inline => {
|
||||
Some(sym::inline | sym::no_inline) => {
|
||||
self.check_doc_inline(attr, meta, hir_id, target, specified_inline)
|
||||
}
|
||||
|
||||
sym::masked => self.check_doc_masked(attr, meta, hir_id, target),
|
||||
Some(sym::masked) => self.check_doc_masked(attr, meta, hir_id, target),
|
||||
|
||||
sym::cfg | sym::hidden | sym::notable_trait => {}
|
||||
Some(sym::cfg | sym::hidden | sym::notable_trait) => {}
|
||||
|
||||
sym::rust_logo => {
|
||||
Some(sym::rust_logo) => {
|
||||
if self.check_attr_crate_level(attr, meta, hir_id)
|
||||
&& !self.tcx.features().rustdoc_internals()
|
||||
{
|
||||
|
@ -2302,7 +2308,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
}
|
||||
|
||||
fn check_macro_use(&self, hir_id: HirId, attr: &Attribute, target: Target) {
|
||||
let name = attr.name_or_empty();
|
||||
let name = attr.name().unwrap();
|
||||
match target {
|
||||
Target::ExternCrate | Target::Mod => {}
|
||||
_ => {
|
||||
|
@ -2334,12 +2340,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
attr.span(),
|
||||
errors::MacroExport::TooManyItems,
|
||||
);
|
||||
} else if meta_item_list[0].name_or_empty() != sym::local_inner_macros {
|
||||
} else if !meta_item_list[0].has_name(sym::local_inner_macros) {
|
||||
self.tcx.emit_node_span_lint(
|
||||
INVALID_MACRO_EXPORT_ARGUMENTS,
|
||||
hir_id,
|
||||
meta_item_list[0].span(),
|
||||
errors::MacroExport::UnknownItem { name: meta_item_list[0].name_or_empty() },
|
||||
errors::MacroExport::InvalidArgument,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
|
@ -2384,33 +2390,28 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
}
|
||||
|
||||
// Warn on useless empty attributes.
|
||||
let note = if (matches!(
|
||||
attr.name_or_empty(),
|
||||
sym::macro_use
|
||||
| sym::allow
|
||||
| sym::expect
|
||||
| sym::warn
|
||||
| sym::deny
|
||||
| sym::forbid
|
||||
| sym::feature
|
||||
| sym::target_feature
|
||||
) && attr.meta_item_list().is_some_and(|list| list.is_empty()))
|
||||
let note = if attr.has_any_name(&[
|
||||
sym::macro_use,
|
||||
sym::allow,
|
||||
sym::expect,
|
||||
sym::warn,
|
||||
sym::deny,
|
||||
sym::forbid,
|
||||
sym::feature,
|
||||
sym::target_feature,
|
||||
]) && attr.meta_item_list().is_some_and(|list| list.is_empty())
|
||||
{
|
||||
errors::UnusedNote::EmptyList { name: attr.name_or_empty() }
|
||||
} else if matches!(
|
||||
attr.name_or_empty(),
|
||||
sym::allow | sym::warn | sym::deny | sym::forbid | sym::expect
|
||||
) && let Some(meta) = attr.meta_item_list()
|
||||
errors::UnusedNote::EmptyList { name: attr.name().unwrap() }
|
||||
} else if attr.has_any_name(&[sym::allow, sym::warn, sym::deny, sym::forbid, sym::expect])
|
||||
&& let Some(meta) = attr.meta_item_list()
|
||||
&& let [meta] = meta.as_slice()
|
||||
&& let Some(item) = meta.meta_item()
|
||||
&& let MetaItemKind::NameValue(_) = &item.kind
|
||||
&& item.path == sym::reason
|
||||
{
|
||||
errors::UnusedNote::NoLints { name: attr.name_or_empty() }
|
||||
} else if matches!(
|
||||
attr.name_or_empty(),
|
||||
sym::allow | sym::warn | sym::deny | sym::forbid | sym::expect
|
||||
) && let Some(meta) = attr.meta_item_list()
|
||||
errors::UnusedNote::NoLints { name: attr.name().unwrap() }
|
||||
} else if attr.has_any_name(&[sym::allow, sym::warn, sym::deny, sym::forbid, sym::expect])
|
||||
&& let Some(meta) = attr.meta_item_list()
|
||||
&& meta.iter().any(|meta| {
|
||||
meta.meta_item().map_or(false, |item| item.path == sym::linker_messages)
|
||||
})
|
||||
|
@ -2443,7 +2444,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
return;
|
||||
}
|
||||
}
|
||||
} else if attr.name_or_empty() == sym::default_method_body_is_const {
|
||||
} else if attr.has_name(sym::default_method_body_is_const) {
|
||||
errors::UnusedNote::DefaultMethodBodyConst
|
||||
} else {
|
||||
return;
|
||||
|
@ -2900,10 +2901,11 @@ fn check_duplicates(
|
|||
if matches!(duplicates, WarnFollowingWordOnly) && !attr.is_word() {
|
||||
return;
|
||||
}
|
||||
let attr_name = attr.name().unwrap();
|
||||
match duplicates {
|
||||
DuplicatesOk => {}
|
||||
WarnFollowing | FutureWarnFollowing | WarnFollowingWordOnly | FutureWarnPreceding => {
|
||||
match seen.entry(attr.name_or_empty()) {
|
||||
match seen.entry(attr_name) {
|
||||
Entry::Occupied(mut entry) => {
|
||||
let (this, other) = if matches!(duplicates, FutureWarnPreceding) {
|
||||
let to_remove = entry.insert(attr.span());
|
||||
|
@ -2930,7 +2932,7 @@ fn check_duplicates(
|
|||
}
|
||||
}
|
||||
}
|
||||
ErrorFollowing | ErrorPreceding => match seen.entry(attr.name_or_empty()) {
|
||||
ErrorFollowing | ErrorPreceding => match seen.entry(attr_name) {
|
||||
Entry::Occupied(mut entry) => {
|
||||
let (this, other) = if matches!(duplicates, ErrorPreceding) {
|
||||
let to_remove = entry.insert(attr.span());
|
||||
|
@ -2938,11 +2940,7 @@ fn check_duplicates(
|
|||
} else {
|
||||
(attr.span(), *entry.get())
|
||||
};
|
||||
tcx.dcx().emit_err(errors::UnusedMultiple {
|
||||
this,
|
||||
other,
|
||||
name: attr.name_or_empty(),
|
||||
});
|
||||
tcx.dcx().emit_err(errors::UnusedMultiple { this, other, name: attr_name });
|
||||
}
|
||||
Entry::Vacant(entry) => {
|
||||
entry.insert(attr.span());
|
||||
|
|
|
@ -28,17 +28,17 @@ impl DebuggerVisualizerCollector<'_> {
|
|||
return;
|
||||
};
|
||||
|
||||
let (visualizer_type, visualizer_path) =
|
||||
match (meta_item.name_or_empty(), meta_item.value_str()) {
|
||||
(sym::natvis_file, Some(value)) => (DebuggerVisualizerType::Natvis, value),
|
||||
(sym::gdb_script_file, Some(value)) => {
|
||||
(DebuggerVisualizerType::GdbPrettyPrinter, value)
|
||||
}
|
||||
(_, _) => {
|
||||
self.sess.dcx().emit_err(DebugVisualizerInvalid { span: meta_item.span });
|
||||
return;
|
||||
}
|
||||
};
|
||||
let (visualizer_type, visualizer_path) = match (meta_item.name(), meta_item.value_str())
|
||||
{
|
||||
(Some(sym::natvis_file), Some(value)) => (DebuggerVisualizerType::Natvis, value),
|
||||
(Some(sym::gdb_script_file), Some(value)) => {
|
||||
(DebuggerVisualizerType::GdbPrettyPrinter, value)
|
||||
}
|
||||
(_, _) => {
|
||||
self.sess.dcx().emit_err(DebugVisualizerInvalid { span: meta_item.span });
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let file = match resolve_path(&self.sess, visualizer_path.as_str(), attr.span) {
|
||||
Ok(file) => file,
|
||||
|
|
|
@ -756,7 +756,7 @@ pub(crate) enum MacroExport {
|
|||
OnDeclMacro,
|
||||
|
||||
#[diag(passes_invalid_macro_export_arguments)]
|
||||
UnknownItem { name: Symbol },
|
||||
InvalidArgument,
|
||||
|
||||
#[diag(passes_invalid_macro_export_arguments_too_many_items)]
|
||||
TooManyItems,
|
||||
|
@ -1045,11 +1045,10 @@ pub(crate) struct AbiInvalidAttribute {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_unrecognized_field)]
|
||||
pub(crate) struct UnrecognizedField {
|
||||
#[diag(passes_unrecognized_argument)]
|
||||
pub(crate) struct UnrecognizedArgument {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub name: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
|
|
|
@ -13,7 +13,7 @@ use rustc_trait_selection::traits;
|
|||
|
||||
use crate::errors::{
|
||||
LayoutAbi, LayoutAlign, LayoutHomogeneousAggregate, LayoutInvalidAttribute, LayoutOf,
|
||||
LayoutSize, UnrecognizedField,
|
||||
LayoutSize, UnrecognizedArgument,
|
||||
};
|
||||
|
||||
pub fn test_layout(tcx: TyCtxt<'_>) {
|
||||
|
@ -79,28 +79,28 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
|
|||
// The `..` are the names of fields to dump.
|
||||
let meta_items = attr.meta_item_list().unwrap_or_default();
|
||||
for meta_item in meta_items {
|
||||
match meta_item.name_or_empty() {
|
||||
match meta_item.name() {
|
||||
// FIXME: this never was about ABI and now this dump arg is confusing
|
||||
sym::abi => {
|
||||
Some(sym::abi) => {
|
||||
tcx.dcx().emit_err(LayoutAbi {
|
||||
span,
|
||||
abi: format!("{:?}", ty_layout.backend_repr),
|
||||
});
|
||||
}
|
||||
|
||||
sym::align => {
|
||||
Some(sym::align) => {
|
||||
tcx.dcx().emit_err(LayoutAlign {
|
||||
span,
|
||||
align: format!("{:?}", ty_layout.align),
|
||||
});
|
||||
}
|
||||
|
||||
sym::size => {
|
||||
Some(sym::size) => {
|
||||
tcx.dcx()
|
||||
.emit_err(LayoutSize { span, size: format!("{:?}", ty_layout.size) });
|
||||
}
|
||||
|
||||
sym::homogeneous_aggregate => {
|
||||
Some(sym::homogeneous_aggregate) => {
|
||||
tcx.dcx().emit_err(LayoutHomogeneousAggregate {
|
||||
span,
|
||||
homogeneous_aggregate: format!(
|
||||
|
@ -111,15 +111,15 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
|
|||
});
|
||||
}
|
||||
|
||||
sym::debug => {
|
||||
Some(sym::debug) => {
|
||||
let normalized_ty = tcx.normalize_erasing_regions(typing_env, ty);
|
||||
// FIXME: using the `Debug` impl here isn't ideal.
|
||||
let ty_layout = format!("{:#?}", *ty_layout);
|
||||
tcx.dcx().emit_err(LayoutOf { span, normalized_ty, ty_layout });
|
||||
}
|
||||
|
||||
name => {
|
||||
tcx.dcx().emit_err(UnrecognizedField { span: meta_item.span(), name });
|
||||
_ => {
|
||||
tcx.dcx().emit_err(UnrecognizedArgument { span: meta_item.span() });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue