use AcceptContext::single_element_list where possible

This commit is contained in:
Sasha Pourcelot
2026-04-04 18:42:42 +00:00
parent cdcecc85ac
commit 6f87e0be69
16 changed files with 106 additions and 125 deletions
@@ -23,16 +23,7 @@ impl<S: Stage> SingleAttributeParser<S> for OptimizeParser {
const TEMPLATE: AttributeTemplate = template!(List: &["size", "speed", "none"]);
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let Some(list) = args.list() else {
let attr_span = cx.attr_span;
cx.adcx().expected_list(attr_span, args);
return None;
};
let Some(single) = list.single() else {
cx.adcx().expected_single_argument(list.span, list.len());
return None;
};
let single = cx.single_element_list(args, cx.attr_span)?;
let res = match single.meta_item().and_then(|i| i.path().word().map(|i| i.name)) {
Some(sym::size) => OptimizeAttr::Size,
@@ -84,22 +75,13 @@ impl<S: Stage> SingleAttributeParser<S> for CoverageParser {
const TEMPLATE: AttributeTemplate = template!(OneOf: &[sym::off, sym::on]);
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let Some(args) = args.list() else {
let attr_span = cx.attr_span;
cx.adcx().expected_specific_argument_and_list(attr_span, &[sym::on, sym::off]);
return None;
};
let Some(arg) = args.single() else {
cx.adcx().expected_single_argument(args.span, args.len());
return None;
};
let arg = cx.single_element_list(args, cx.attr_span)?;
let mut fail_incorrect_argument =
|span| cx.adcx().expected_specific_argument(span, &[sym::on, sym::off]);
let Some(arg) = arg.meta_item() else {
fail_incorrect_argument(args.span);
fail_incorrect_argument(arg.span());
return None;
};
@@ -20,15 +20,7 @@ fn extend(
cx: &mut AcceptContext<'_, '_, S>,
args: &ArgParser,
) -> impl IntoIterator<Item = Self::Item> {
let Some(l) = args.list() else {
let attr_span = cx.attr_span;
cx.adcx().expected_list(attr_span, args);
return None;
};
let Some(single) = l.single() else {
cx.adcx().expected_single_argument(l.span, l.len());
return None;
};
let single = cx.single_element_list(args, cx.attr_span)?;
let Some(mi) = single.meta_item() else {
cx.adcx().expected_name_value(single.span(), None);
return None;
@@ -20,11 +20,7 @@ impl<S: Stage> SingleAttributeParser<S> for InstructionSetParser {
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
const POSSIBLE_SYMBOLS: &[Symbol] = &[sym::arm_a32, sym::arm_t32];
const POSSIBLE_ARM_SYMBOLS: &[Symbol] = &[sym::a32, sym::t32];
let Some(maybe_meta_item) = args.list().and_then(MetaItemListParser::single) else {
let attr_span = cx.attr_span;
cx.adcx().expected_specific_argument(attr_span, POSSIBLE_SYMBOLS);
return None;
};
let maybe_meta_item = cx.single_element_list(args, cx.attr_span)?;
let Some(meta_item) = maybe_meta_item.meta_item() else {
cx.adcx().expected_specific_argument(maybe_meta_item.span(), POSSIBLE_SYMBOLS);
@@ -388,12 +388,7 @@ fn parse_link_cfg<S: Stage>(
cx.adcx().duplicate_key(item.span(), sym::cfg);
return true;
}
let Some(link_cfg) = item.args().list() else {
cx.adcx().expected_list(item.span(), item.args());
return true;
};
let Some(link_cfg) = link_cfg.single() else {
cx.adcx().expected_single_argument(item.span(), link_cfg.len());
let Some(link_cfg) = cx.single_element_list(item.args(), item.span()) else {
return true;
};
if !features.link_cfg() {
@@ -175,15 +175,7 @@ impl<S: Stage> SingleAttributeParser<S> for CollapseDebugInfoParser {
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::MacroDef)]);
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let Some(list) = args.list() else {
let attr_span = cx.attr_span;
cx.adcx().expected_list(attr_span, args);
return None;
};
let Some(single) = list.single() else {
cx.adcx().expected_single_argument(list.span, list.len());
return None;
};
let single = cx.single_element_list(args, cx.attr_span)?;
let Some(mi) = single.meta_item() else {
cx.adcx().expected_not_literal(single.span());
return None;
@@ -195,11 +195,7 @@ impl<S: Stage> SingleAttributeParser<S> for RustcLintOptDenyFieldAccessParser {
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Field)]);
const TEMPLATE: AttributeTemplate = template!(Word);
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let Some(arg) = args.list().and_then(MetaItemListParser::single) else {
let attr_span = cx.attr_span;
cx.adcx().expected_single_argument(attr_span, 2);
return None;
};
let arg = cx.single_element_list(args, cx.attr_span)?;
let MetaItemOrLitParser::Lit(MetaItemLit { kind: LitKind::Str(lint_message, _), .. }) = arg
else {
@@ -375,19 +371,10 @@ impl<S: Stage> SingleAttributeParser<S> for RustcDeprecatedSafe2024Parser {
const TEMPLATE: AttributeTemplate = template!(List: &[r#"audit_that = "...""#]);
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let Some(args) = args.list() else {
let attr_span = cx.attr_span;
cx.adcx().expected_list(attr_span, args);
return None;
};
let Some(single) = args.single() else {
cx.adcx().expected_single_argument(args.span, args.len());
return None;
};
let single = cx.single_element_list(args, cx.attr_span)?;
let Some(arg) = single.meta_item() else {
cx.adcx().expected_name_value(args.span, None);
cx.adcx().expected_name_value(single.span(), None);
return None;
};
@@ -1082,11 +1069,7 @@ fn extend(
if !cx.cx.sess.opts.unstable_opts.query_dep_graph {
cx.emit_err(AttributeRequiresOpt { span: cx.attr_span, opt: "-Z query-dep-graph" });
}
let Some(item) = args.list().and_then(|l| l.single()) else {
let inner_span = cx.inner_span;
cx.adcx().expected_single_argument(inner_span, 2);
return None;
};
let item = cx.single_element_list(args, cx.attr_span)?;
let Some(ident) = item.meta_item().and_then(|item| item.ident()) else {
cx.adcx().expected_identifier(item.span());
return None;
@@ -208,16 +208,7 @@ impl<S: Stage> SingleAttributeParser<S> for TestRunnerParser {
const TEMPLATE: AttributeTemplate = template!(List: &["path"]);
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let Some(list) = args.list() else {
let attr_span = cx.attr_span;
cx.adcx().expected_list(attr_span, args);
return None;
};
let Some(single) = list.single() else {
cx.adcx().expected_single_argument(list.span, list.len());
return None;
};
let single = cx.single_element_list(args, cx.attr_span)?;
let Some(meta) = single.meta_item() else {
cx.adcx().expected_not_literal(single.span());
@@ -41,15 +41,7 @@ pub(crate) fn parse_single_integer<S: Stage>(
cx: &mut AcceptContext<'_, '_, S>,
args: &ArgParser,
) -> Option<u128> {
let Some(list) = args.list() else {
let attr_span = cx.attr_span;
cx.adcx().expected_list(attr_span, args);
return None;
};
let Some(single) = list.single() else {
cx.adcx().expected_single_argument(list.span, list.len());
return None;
};
let single = cx.single_element_list(args, cx.attr_span)?;
let Some(lit) = single.lit() else {
cx.adcx().expected_integer_literal(single.span());
return None;
+34 -2
View File
@@ -60,7 +60,7 @@
use crate::attributes::traits::*;
use crate::attributes::transparency::*;
use crate::attributes::{AttributeParser as _, Combine, Single, WithoutArgs};
use crate::parser::{ArgParser, RefPathParser};
use crate::parser::{ArgParser, MetaItemOrLitParser, RefPathParser};
use crate::session_diagnostics::{
AttributeParseError, AttributeParseErrorReason, AttributeParseErrorSuggestions,
ParsedDescription,
@@ -502,6 +502,36 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
pub(crate) fn adcx(&mut self) -> AttributeDiagnosticContext<'_, 'f, 'sess, S> {
AttributeDiagnosticContext { ctx: self, custom_suggestions: Vec::new() }
}
/// Asserts that this MetaItem is a list that contains a single element. Emits an error and
/// returns `None` if it is not the case.
///
/// Some examples:
///
/// - In `#[allow(warnings)]`, `warnings` is returned
/// - In `#[cfg_attr(docsrs, doc = "foo")]`, `None` is returned, "expected a single argument
/// here" is emitted.
/// - In `#[cfg()]`, `None` is returned, "expected an argument here" is emitted.
///
/// The provided span is used as a fallback for diagnostic generation in case `arg` does not
/// contain any. It should be the span of the node that contains `arg`.
pub(crate) fn single_element_list<'arg>(
&mut self,
arg: &'arg ArgParser,
span: Span,
) -> Option<&'arg MetaItemOrLitParser> {
let ArgParser::List(l) = arg else {
self.adcx().expected_list(span, arg);
return None;
};
let Some(single) = l.single() else {
self.adcx().expected_single_argument(l.span, l.len());
return None;
};
Some(single)
}
}
impl<'f, 'sess, S: Stage> Deref for AcceptContext<'f, 'sess, S> {
@@ -689,6 +719,8 @@ pub(crate) fn expected_integer_literal_in_range(
)
}
/// The provided span is used as a fallback in case `args` does not contain any. It should be
/// the span of the node that contains `args`.
pub(crate) fn expected_list(&mut self, span: Span, args: &ArgParser) -> ErrorGuaranteed {
let span = match args {
ArgParser::NoArgs => span,
@@ -745,7 +777,7 @@ pub(crate) fn duplicate_key(&mut self, span: Span, key: Symbol) -> ErrorGuarante
self.emit_parse_error(span, AttributeParseErrorReason::DuplicateKey(key))
}
/// An error that should be emitted when a [`MetaItemOrLitParser`](crate::parser::MetaItemOrLitParser)
/// An error that should be emitted when a [`MetaItemOrLitParser`]
/// was expected *not* to be a literal, but instead a meta item.
pub(crate) fn expected_not_literal(&mut self, span: Span) -> ErrorGuaranteed {
self.emit_parse_error(span, AttributeParseErrorReason::ExpectedNotLiteral)
+2 -2
View File
@@ -314,7 +314,7 @@ error[E0539]: malformed `coverage` attribute input
--> $DIR/malformed-attrs.rs:92:1
|
LL | #[coverage]
| ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
| ^^^^^^^^^^^ expected this to be a list
|
help: try changing it to one of the following valid forms of the attribute
|
@@ -353,7 +353,7 @@ error[E0539]: malformed `instruction_set` attribute input
LL | #[instruction_set]
| ^^^^^^^^^^^^^^^^^^
| |
| valid arguments are `arm::a32` or `arm::t32`
| expected this to be a list
| help: must be of the form: `#[instruction_set(set)]`
|
= note: for more information, visit <https://doc.rust-lang.org/reference/attributes/codegen.html#the-instruction_set-attribute>
@@ -2,7 +2,7 @@ error[E0539]: malformed `coverage` attribute input
--> $DIR/bad-attr-ice.rs:11:1
|
LL | #[coverage]
| ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
| ^^^^^^^^^^^ expected this to be a list
|
help: try changing it to one of the following valid forms of the attribute
|
@@ -12,7 +12,7 @@ error[E0539]: malformed `coverage` attribute input
--> $DIR/bad-attr-ice.rs:11:1
|
LL | #[coverage]
| ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
| ^^^^^^^^^^^ expected this to be a list
|
help: try changing it to one of the following valid forms of the attribute
|
+4 -2
View File
@@ -26,7 +26,7 @@ error[E0539]: malformed `coverage` attribute input
--> $DIR/bad-syntax.rs:17:1
|
LL | #[coverage]
| ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
| ^^^^^^^^^^^ expected this to be a list
|
help: try changing it to one of the following valid forms of the attribute
|
@@ -39,7 +39,9 @@ error[E0539]: malformed `coverage` attribute input
--> $DIR/bad-syntax.rs:20:1
|
LL | #[coverage = true]
| ^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
| ^^^^^^^^^^^------^
| |
| expected this to be a list
|
help: try changing it to one of the following valid forms of the attribute
|
+36 -12
View File
@@ -2,7 +2,9 @@ error[E0539]: malformed `coverage` attribute input
--> $DIR/name-value.rs:12:1
|
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
| ^^^^^^^^^^^-------^
| |
| expected this to be a list
|
help: try changing it to one of the following valid forms of the attribute
|
@@ -17,7 +19,9 @@ error[E0539]: malformed `coverage` attribute input
--> $DIR/name-value.rs:17:5
|
LL | #![coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
| ^^^^^^^^^^^^-------^
| |
| expected this to be a list
|
help: try changing it to one of the following valid forms of the attribute
|
@@ -32,7 +36,9 @@ error[E0539]: malformed `coverage` attribute input
--> $DIR/name-value.rs:21:1
|
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
| ^^^^^^^^^^^-------^
| |
| expected this to be a list
|
help: try changing it to one of the following valid forms of the attribute
|
@@ -55,7 +61,9 @@ error[E0539]: malformed `coverage` attribute input
--> $DIR/name-value.rs:26:1
|
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
| ^^^^^^^^^^^-------^
| |
| expected this to be a list
|
help: try changing it to one of the following valid forms of the attribute
|
@@ -70,7 +78,9 @@ error[E0539]: malformed `coverage` attribute input
--> $DIR/name-value.rs:29:5
|
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
| ^^^^^^^^^^^-------^
| |
| expected this to be a list
|
help: try changing it to one of the following valid forms of the attribute
|
@@ -93,7 +103,9 @@ error[E0539]: malformed `coverage` attribute input
--> $DIR/name-value.rs:35:1
|
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
| ^^^^^^^^^^^-------^
| |
| expected this to be a list
|
help: try changing it to one of the following valid forms of the attribute
|
@@ -116,7 +128,9 @@ error[E0539]: malformed `coverage` attribute input
--> $DIR/name-value.rs:39:5
|
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
| ^^^^^^^^^^^-------^
| |
| expected this to be a list
|
help: try changing it to one of the following valid forms of the attribute
|
@@ -139,7 +153,9 @@ error[E0539]: malformed `coverage` attribute input
--> $DIR/name-value.rs:44:5
|
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
| ^^^^^^^^^^^-------^
| |
| expected this to be a list
|
help: try changing it to one of the following valid forms of the attribute
|
@@ -162,7 +178,9 @@ error[E0539]: malformed `coverage` attribute input
--> $DIR/name-value.rs:50:1
|
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
| ^^^^^^^^^^^-------^
| |
| expected this to be a list
|
help: try changing it to one of the following valid forms of the attribute
|
@@ -177,7 +195,9 @@ error[E0539]: malformed `coverage` attribute input
--> $DIR/name-value.rs:53:5
|
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
| ^^^^^^^^^^^-------^
| |
| expected this to be a list
|
help: try changing it to one of the following valid forms of the attribute
|
@@ -200,7 +220,9 @@ error[E0539]: malformed `coverage` attribute input
--> $DIR/name-value.rs:58:5
|
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
| ^^^^^^^^^^^-------^
| |
| expected this to be a list
|
help: try changing it to one of the following valid forms of the attribute
|
@@ -223,7 +245,9 @@ error[E0539]: malformed `coverage` attribute input
--> $DIR/name-value.rs:64:1
|
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
| ^^^^^^^^^^^-------^
| |
| expected this to be a list
|
help: try changing it to one of the following valid forms of the attribute
|
+12 -12
View File
@@ -2,7 +2,7 @@ error[E0539]: malformed `coverage` attribute input
--> $DIR/word-only.rs:12:1
|
LL | #[coverage]
| ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
| ^^^^^^^^^^^ expected this to be a list
|
help: try changing it to one of the following valid forms of the attribute
|
@@ -15,7 +15,7 @@ error[E0539]: malformed `coverage` attribute input
--> $DIR/word-only.rs:17:5
|
LL | #![coverage]
| ^^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
| ^^^^^^^^^^^^ expected this to be a list
|
help: try changing it to one of the following valid forms of the attribute
|
@@ -28,7 +28,7 @@ error[E0539]: malformed `coverage` attribute input
--> $DIR/word-only.rs:21:1
|
LL | #[coverage]
| ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
| ^^^^^^^^^^^ expected this to be a list
|
help: try changing it to one of the following valid forms of the attribute
|
@@ -49,7 +49,7 @@ error[E0539]: malformed `coverage` attribute input
--> $DIR/word-only.rs:26:1
|
LL | #[coverage]
| ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
| ^^^^^^^^^^^ expected this to be a list
|
help: try changing it to one of the following valid forms of the attribute
|
@@ -62,7 +62,7 @@ error[E0539]: malformed `coverage` attribute input
--> $DIR/word-only.rs:29:5
|
LL | #[coverage]
| ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
| ^^^^^^^^^^^ expected this to be a list
|
help: try changing it to one of the following valid forms of the attribute
|
@@ -83,7 +83,7 @@ error[E0539]: malformed `coverage` attribute input
--> $DIR/word-only.rs:35:1
|
LL | #[coverage]
| ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
| ^^^^^^^^^^^ expected this to be a list
|
help: try changing it to one of the following valid forms of the attribute
|
@@ -104,7 +104,7 @@ error[E0539]: malformed `coverage` attribute input
--> $DIR/word-only.rs:39:5
|
LL | #[coverage]
| ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
| ^^^^^^^^^^^ expected this to be a list
|
help: try changing it to one of the following valid forms of the attribute
|
@@ -125,7 +125,7 @@ error[E0539]: malformed `coverage` attribute input
--> $DIR/word-only.rs:44:5
|
LL | #[coverage]
| ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
| ^^^^^^^^^^^ expected this to be a list
|
help: try changing it to one of the following valid forms of the attribute
|
@@ -146,7 +146,7 @@ error[E0539]: malformed `coverage` attribute input
--> $DIR/word-only.rs:50:1
|
LL | #[coverage]
| ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
| ^^^^^^^^^^^ expected this to be a list
|
help: try changing it to one of the following valid forms of the attribute
|
@@ -159,7 +159,7 @@ error[E0539]: malformed `coverage` attribute input
--> $DIR/word-only.rs:53:5
|
LL | #[coverage]
| ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
| ^^^^^^^^^^^ expected this to be a list
|
help: try changing it to one of the following valid forms of the attribute
|
@@ -180,7 +180,7 @@ error[E0539]: malformed `coverage` attribute input
--> $DIR/word-only.rs:58:5
|
LL | #[coverage]
| ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
| ^^^^^^^^^^^ expected this to be a list
|
help: try changing it to one of the following valid forms of the attribute
|
@@ -201,7 +201,7 @@ error[E0539]: malformed `coverage` attribute input
--> $DIR/word-only.rs:64:1
|
LL | #[coverage]
| ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
| ^^^^^^^^^^^ expected this to be a list
|
help: try changing it to one of the following valid forms of the attribute
|
+3 -3
View File
@@ -2,9 +2,9 @@ error[E0805]: malformed `link` attribute input
--> $DIR/issue-43926.rs:1:1
|
LL | #[link(name = "foo", cfg())]
| ^^^^^^^^^^^^^^^^^^^^^-----^^
| |
| expected an argument here
| ^^^^^^^^^^^^^^^^^^^^^^^^--^^
| |
| expected an argument here
|
= note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>