mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-26 13:01:27 +03:00
Add a simpler, harder to misuse, attribute parsing API
This commit is contained in:
@@ -81,7 +81,7 @@ fn parse_unstable<S: Stage>(
|
||||
) -> impl IntoIterator<Item = Symbol> {
|
||||
let mut res = Vec::new();
|
||||
|
||||
let Some(list) = args.list() else {
|
||||
let Some(list) = args.as_list() else {
|
||||
cx.emit_err(session_diagnostics::ExpectsFeatureList {
|
||||
span: cx.attr_span,
|
||||
name: symbol.to_ident_string(),
|
||||
|
||||
@@ -44,13 +44,9 @@ pub fn parse_cfg<S: Stage>(
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
args: &ArgParser,
|
||||
) -> Option<CfgEntry> {
|
||||
let ArgParser::List(list) = args else {
|
||||
let attr_span = cx.attr_span;
|
||||
cx.adcx().expected_list(attr_span, args);
|
||||
return None;
|
||||
};
|
||||
let list = cx.expect_list(args, cx.attr_span)?;
|
||||
|
||||
let Some(single) = list.single() else {
|
||||
let Some(single) = list.as_single() else {
|
||||
let target = cx.target;
|
||||
let mut adcx = cx.adcx();
|
||||
if list.is_empty() {
|
||||
@@ -93,7 +89,7 @@ pub fn parse_cfg_entry<S: Stage>(
|
||||
MetaItemOrLitParser::MetaItemParser(meta) => match meta.args() {
|
||||
ArgParser::List(list) => match meta.path().word_sym() {
|
||||
Some(sym::not) => {
|
||||
let Some(single) = list.single() else {
|
||||
let Some(single) = list.as_single() else {
|
||||
return Err(cx.adcx().expected_single_argument(list.span, list.len()));
|
||||
};
|
||||
CfgEntry::Not(Box::new(parse_cfg_entry(cx, single)?), list.span)
|
||||
@@ -136,7 +132,7 @@ fn parse_cfg_entry_version<S: Stage>(
|
||||
meta_span: Span,
|
||||
) -> Result<CfgEntry, ErrorGuaranteed> {
|
||||
try_gate_cfg(sym::version, meta_span, cx.sess(), cx.features_option());
|
||||
let Some(version) = list.single() else {
|
||||
let Some(version) = list.as_single() else {
|
||||
return Err(
|
||||
cx.emit_err(session_diagnostics::ExpectedSingleVersionLiteral { span: list.span })
|
||||
);
|
||||
|
||||
@@ -24,7 +24,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 single = cx.single_element_list(args, cx.attr_span)?;
|
||||
let single = cx.expect_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,
|
||||
@@ -75,7 +75,7 @@ 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 arg = cx.single_element_list(args, cx.attr_span)?;
|
||||
let arg = cx.expect_single_element_list(args, cx.attr_span)?;
|
||||
|
||||
let mut fail_incorrect_argument =
|
||||
|span| cx.adcx().expected_specific_argument(span, &[sym::on, sym::off]);
|
||||
@@ -371,8 +371,7 @@ impl<S: Stage> AttributeParser<S> for UsedParser {
|
||||
let used_by = match args {
|
||||
ArgParser::NoArgs => UsedBy::Default,
|
||||
ArgParser::List(list) => {
|
||||
let Some(l) = list.single() else {
|
||||
cx.adcx().expected_single_argument(list.span, list.len());
|
||||
let Some(l) = cx.expect_single(list) else {
|
||||
return;
|
||||
};
|
||||
|
||||
@@ -463,9 +462,7 @@ fn parse_tf_attribute<S: Stage>(
|
||||
args: &ArgParser,
|
||||
) -> impl IntoIterator<Item = (Symbol, Span)> {
|
||||
let mut features = Vec::new();
|
||||
let ArgParser::List(list) = args else {
|
||||
let attr_span = cx.attr_span;
|
||||
cx.adcx().expected_list(attr_span, args);
|
||||
let Some(list) = cx.expect_list(args, cx.attr_span) else {
|
||||
return features;
|
||||
};
|
||||
if list.is_empty() {
|
||||
@@ -588,11 +585,7 @@ impl<S: Stage> SingleAttributeParser<S> for SanitizeParser {
|
||||
]);
|
||||
|
||||
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 list = cx.expect_list(args, cx.attr_span)?;
|
||||
|
||||
let mut on_set = SanitizerSet::empty();
|
||||
let mut off_set = SanitizerSet::empty();
|
||||
@@ -719,11 +712,7 @@ impl<S: Stage> SingleAttributeParser<S> for PatchableFunctionEntryParser {
|
||||
const TEMPLATE: AttributeTemplate = template!(List: &["prefix_nops = m, entry_nops = n"]);
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
|
||||
let Some(meta_item_list) = args.list() else {
|
||||
let attr_span = cx.attr_span;
|
||||
cx.adcx().expected_list(attr_span, args);
|
||||
return None;
|
||||
};
|
||||
let meta_item_list = cx.expect_list(args, cx.attr_span)?;
|
||||
|
||||
let mut prefix = None;
|
||||
let mut entry = None;
|
||||
|
||||
@@ -12,11 +12,7 @@ impl<S: Stage> AttributeParser<S> for ConfusablesParser {
|
||||
&[sym::rustc_confusables],
|
||||
template!(List: &[r#""name1", "name2", ..."#]),
|
||||
|this, cx, args| {
|
||||
let Some(list) = args.list() else {
|
||||
let attr_span = cx.attr_span;
|
||||
cx.adcx().expected_list(attr_span, args);
|
||||
return;
|
||||
};
|
||||
let Some(list) = cx.expect_list(args, cx.attr_span) else { return };
|
||||
|
||||
if list.is_empty() {
|
||||
cx.emit_err(EmptyConfusables { span: cx.attr_span });
|
||||
|
||||
@@ -314,9 +314,7 @@ fn extend(
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
args: &ArgParser,
|
||||
) -> impl IntoIterator<Item = Self::Item> {
|
||||
let ArgParser::List(list) = args else {
|
||||
let attr_span = cx.attr_span;
|
||||
cx.adcx().expected_list(attr_span, args);
|
||||
let Some(list) = cx.expect_list(args, cx.attr_span) else {
|
||||
return Vec::new();
|
||||
};
|
||||
|
||||
@@ -362,9 +360,7 @@ fn extend(
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
args: &ArgParser,
|
||||
) -> impl IntoIterator<Item = Self::Item> {
|
||||
let ArgParser::List(list) = args else {
|
||||
let attr_span = cx.attr_span;
|
||||
cx.adcx().expected_list(attr_span, args);
|
||||
let Some(list) = cx.expect_list(args, cx.attr_span) else {
|
||||
return Vec::new();
|
||||
};
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ fn extend(
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
args: &ArgParser,
|
||||
) -> impl IntoIterator<Item = Self::Item> {
|
||||
let single = cx.single_element_list(args, cx.attr_span)?;
|
||||
let single = cx.expect_single_element_list(args, cx.attr_span)?;
|
||||
let Some(mi) = single.meta_item() else {
|
||||
cx.adcx().expected_name_value(single.span(), None);
|
||||
return None;
|
||||
|
||||
@@ -304,7 +304,7 @@ fn parse_directive_items<'p, S: Stage>(
|
||||
}
|
||||
(Mode::RustcOnUnimplemented, sym::on) => {
|
||||
if is_root {
|
||||
let items = or_malformed!(item.args().list()?);
|
||||
let items = or_malformed!(item.args().as_list()?);
|
||||
let mut iter = items.mixed();
|
||||
let condition: &MetaItemOrLitParser = match iter.next() {
|
||||
Some(c) => c,
|
||||
@@ -478,7 +478,7 @@ fn parse_predicate(input: &MetaItemOrLitParser) -> Result<Predicate, InvalidOnCl
|
||||
sym::any => Ok(Predicate::Any(parse_predicate_sequence(mis)?)),
|
||||
sym::all => Ok(Predicate::All(parse_predicate_sequence(mis)?)),
|
||||
sym::not => {
|
||||
if let Some(single) = mis.single() {
|
||||
if let Some(single) = mis.as_single() {
|
||||
Ok(Predicate::Not(Box::new(parse_predicate(single)?)))
|
||||
} else {
|
||||
Err(InvalidOnClause::ExpectedOnePredInNot { span: mis.span })
|
||||
|
||||
@@ -199,7 +199,7 @@ fn parse_single_test_doc_attr_item<S: Stage>(
|
||||
self.attribute.no_crate_inject = Some(path.span())
|
||||
}
|
||||
Some(sym::attr) => {
|
||||
let Some(list) = args.list() else {
|
||||
let Some(list) = args.as_list() else {
|
||||
// FIXME: remove this method once merged and uncomment the line below instead.
|
||||
// cx.expected_list(cx.attr_span, args);
|
||||
let span = cx.attr_span;
|
||||
@@ -587,7 +587,7 @@ macro_rules! string_arg_and_crate_level {
|
||||
}),
|
||||
Some(sym::auto_cfg) => self.parse_auto_cfg(cx, path, args),
|
||||
Some(sym::test) => {
|
||||
let Some(list) = args.list() else {
|
||||
let Some(list) = args.as_list() else {
|
||||
cx.emit_dyn_lint(
|
||||
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
|
||||
|dcx, level| DocTestTakesList.into_diag(dcx, level),
|
||||
|
||||
@@ -37,10 +37,7 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
|
||||
match args {
|
||||
ArgParser::NoArgs => Some(AttributeKind::Inline(InlineAttr::Hint, cx.attr_span)),
|
||||
ArgParser::List(list) => {
|
||||
let Some(l) = list.single() else {
|
||||
cx.adcx().expected_single_argument(list.span, list.len());
|
||||
return None;
|
||||
};
|
||||
let l = cx.expect_single(list)?;
|
||||
|
||||
match l.meta_item().and_then(|i| i.path().word_sym()) {
|
||||
Some(sym::always) => {
|
||||
@@ -78,10 +75,7 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
|
||||
let reason = match args {
|
||||
ArgParser::NoArgs => None,
|
||||
ArgParser::List(list) => {
|
||||
let Some(l) = list.single() else {
|
||||
cx.adcx().expected_single_argument(list.span, list.len());
|
||||
return None;
|
||||
};
|
||||
let l = cx.expect_single(list)?;
|
||||
|
||||
let Some(reason) = l.lit().and_then(|i| i.kind.str()) else {
|
||||
cx.adcx().expected_string_literal(l.span(), l.lit());
|
||||
|
||||
@@ -19,7 +19,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 maybe_meta_item = cx.single_element_list(args, cx.attr_span)?;
|
||||
let maybe_meta_item = cx.expect_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);
|
||||
|
||||
@@ -390,7 +390,7 @@ fn parse_link_cfg<S: Stage>(
|
||||
cx.adcx().duplicate_key(item.span(), sym::cfg);
|
||||
return true;
|
||||
}
|
||||
let Some(link_cfg) = cx.single_element_list(item.args(), item.span()) else {
|
||||
let Some(link_cfg) = cx.expect_single_element_list(item.args(), item.span()) else {
|
||||
return true;
|
||||
};
|
||||
if !features.link_cfg() {
|
||||
|
||||
@@ -142,7 +142,7 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
|
||||
let local_inner_macros = match args {
|
||||
ArgParser::NoArgs => false,
|
||||
ArgParser::List(list) => {
|
||||
let Some(l) = list.single() else {
|
||||
let Some(l) = list.as_single() else {
|
||||
cx.adcx().warn_ill_formed_attribute_input(INVALID_MACRO_EXPORT_ARGUMENTS);
|
||||
return None;
|
||||
};
|
||||
@@ -174,7 +174,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 single = cx.single_element_list(args, cx.attr_span)?;
|
||||
let single = cx.expect_single_element_list(args, cx.attr_span)?;
|
||||
let Some(mi) = single.meta_item() else {
|
||||
cx.adcx().expected_not_literal(single.span());
|
||||
return None;
|
||||
|
||||
@@ -57,7 +57,7 @@ fn parse_derive_like<S: Stage>(
|
||||
args: &ArgParser,
|
||||
trait_name_mandatory: bool,
|
||||
) -> Option<(Option<Symbol>, ThinVec<Symbol>)> {
|
||||
let Some(list) = args.list() else {
|
||||
let Some(list) = args.as_list() else {
|
||||
// For #[rustc_builtin_macro], it is permitted to leave out the trait name
|
||||
if args.no_args().is_ok() && !trait_name_mandatory {
|
||||
return Some((None, ThinVec::new()));
|
||||
@@ -101,10 +101,7 @@ fn parse_derive_like<S: Stage>(
|
||||
cx.adcx().expected_specific_argument(attrs.span(), &[sym::attributes]);
|
||||
return None;
|
||||
}
|
||||
let Some(attr_list) = attr_list.args().list() else {
|
||||
cx.adcx().expected_list(attrs.span(), attr_list.args());
|
||||
return None;
|
||||
};
|
||||
let attr_list = cx.expect_list(attr_list.args(), attrs.span())?;
|
||||
|
||||
// Parse item in `attributes(...)` argument
|
||||
for attr in attr_list.mixed() {
|
||||
|
||||
@@ -22,11 +22,7 @@ impl<S: Stage> SingleAttributeParser<S> for CustomMirParser {
|
||||
const TEMPLATE: AttributeTemplate = template!(List: &[r#"dialect = "...", phase = "...""#]);
|
||||
|
||||
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 list = cx.expect_list(args, cx.attr_span)?;
|
||||
|
||||
let mut dialect = None;
|
||||
let mut phase = None;
|
||||
|
||||
@@ -32,9 +32,7 @@ fn extend(
|
||||
) -> impl IntoIterator<Item = Self::Item> {
|
||||
let mut reprs = Vec::new();
|
||||
|
||||
let Some(list) = args.list() else {
|
||||
let attr_span = cx.attr_span;
|
||||
cx.adcx().expected_list(attr_span, args);
|
||||
let Some(list) = cx.expect_list(args, cx.attr_span) else {
|
||||
return reprs;
|
||||
};
|
||||
|
||||
@@ -197,7 +195,7 @@ fn parse_repr_align<S: Stage>(
|
||||
) -> Option<ReprAttr> {
|
||||
use AlignKind::*;
|
||||
|
||||
let Some(align) = list.single() else {
|
||||
let Some(align) = list.as_single() else {
|
||||
match align_kind {
|
||||
Packed => {
|
||||
cx.emit_err(session_diagnostics::IncorrectReprFormatPackedOneOrZeroArg {
|
||||
@@ -296,8 +294,7 @@ fn parse<S: Stage>(&mut self, cx: &mut AcceptContext<'_, '_, S>, args: &ArgParse
|
||||
cx.adcx().expected_list(attr_span, args);
|
||||
}
|
||||
ArgParser::List(list) => {
|
||||
let Some(align) = list.single() else {
|
||||
cx.adcx().expected_single_argument(list.span, list.len());
|
||||
let Some(align) = cx.expect_single(list) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
||||
@@ -96,9 +96,7 @@ fn extend(
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
args: &ArgParser,
|
||||
) -> impl IntoIterator<Item = Self::Item> {
|
||||
let ArgParser::List(items) = args else {
|
||||
let attr_span = cx.attr_span;
|
||||
cx.adcx().expected_list(attr_span, args);
|
||||
let Some(items) = cx.expect_list(args, cx.attr_span) else {
|
||||
return vec![];
|
||||
};
|
||||
|
||||
|
||||
@@ -30,11 +30,7 @@ impl<S: Stage> SingleAttributeParser<S> for RustcMustImplementOneOfParser {
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
|
||||
const TEMPLATE: AttributeTemplate = template!(List: &["function1, function2, ..."]);
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
|
||||
let Some(list) = args.list() else {
|
||||
let span = cx.attr_span;
|
||||
cx.adcx().expected_list(span, args);
|
||||
return None;
|
||||
};
|
||||
let list = cx.expect_list(args, cx.attr_span)?;
|
||||
|
||||
let mut fn_names = ThinVec::new();
|
||||
|
||||
@@ -130,11 +126,7 @@ impl<S: Stage> SingleAttributeParser<S> for RustcLegacyConstGenericsParser {
|
||||
const TEMPLATE: AttributeTemplate = template!(List: &["N"]);
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
|
||||
let ArgParser::List(meta_items) = args else {
|
||||
let attr_span = cx.attr_span;
|
||||
cx.adcx().expected_list(attr_span, args);
|
||||
return None;
|
||||
};
|
||||
let meta_items = cx.expect_list(args, cx.attr_span)?;
|
||||
|
||||
let mut parsed_indexes = ThinVec::new();
|
||||
let mut errored = false;
|
||||
@@ -185,7 +177,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 arg = cx.single_element_list(args, cx.attr_span)?;
|
||||
let arg = cx.expect_single_element_list(args, cx.attr_span)?;
|
||||
|
||||
let MetaItemOrLitParser::Lit(MetaItemLit { kind: LitKind::Str(lint_message, _), .. }) = arg
|
||||
else {
|
||||
@@ -210,11 +202,7 @@ fn parse_cgu_fields<S: Stage>(
|
||||
args: &ArgParser,
|
||||
accepts_kind: bool,
|
||||
) -> Option<(Symbol, Symbol, Option<CguKind>)> {
|
||||
let Some(args) = args.list() else {
|
||||
let attr_span = cx.attr_span;
|
||||
cx.adcx().expected_list(attr_span, args);
|
||||
return None;
|
||||
};
|
||||
let args = cx.expect_list(args, cx.attr_span)?;
|
||||
|
||||
let mut cfg = None::<(Symbol, Span)>;
|
||||
let mut module = None::<(Symbol, Span)>;
|
||||
@@ -359,7 +347,7 @@ 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 single = cx.single_element_list(args, cx.attr_span)?;
|
||||
let single = cx.expect_single_element_list(args, cx.attr_span)?;
|
||||
|
||||
let Some(arg) = single.meta_item() else {
|
||||
cx.adcx().expected_name_value(single.span(), None);
|
||||
@@ -418,11 +406,7 @@ impl<S: Stage> SingleAttributeParser<S> for RustcNeverTypeOptionsParser {
|
||||
]);
|
||||
|
||||
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 list = cx.expect_list(args, cx.attr_span)?;
|
||||
|
||||
let mut fallback = None::<Ident>;
|
||||
let mut diverging_block_default = None::<Ident>;
|
||||
@@ -703,9 +687,7 @@ fn extend(
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
args: &ArgParser,
|
||||
) -> impl IntoIterator<Item = Self::Item> {
|
||||
let Some(list) = args.list() else {
|
||||
let attr_span = cx.attr_span;
|
||||
cx.adcx().expected_list(attr_span, args);
|
||||
let Some(list) = cx.expect_list(args, cx.attr_span) else {
|
||||
return ThinVec::new();
|
||||
};
|
||||
|
||||
@@ -825,11 +807,8 @@ 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(list) = args.list() else {
|
||||
let attr_span = cx.attr_span;
|
||||
cx.adcx().expected_list(attr_span, args);
|
||||
return None;
|
||||
};
|
||||
let list = cx.expect_list(args, cx.attr_span)?;
|
||||
|
||||
let mut except = None;
|
||||
let mut loaded_from_disk = None;
|
||||
let mut cfg = None;
|
||||
@@ -926,11 +905,7 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
|
||||
match args {
|
||||
ArgParser::NoArgs => Some(AttributeKind::RustcIfThisChanged(cx.attr_span, None)),
|
||||
ArgParser::List(list) => {
|
||||
let Some(item) = list.single() else {
|
||||
let attr_span = cx.attr_span;
|
||||
cx.adcx().expected_single_argument(attr_span, list.len());
|
||||
return None;
|
||||
};
|
||||
let item = cx.expect_single(list)?;
|
||||
let Some(ident) = item.meta_item().and_then(|item| item.ident()) else {
|
||||
cx.adcx().expected_identifier(item.span());
|
||||
return None;
|
||||
@@ -988,7 +963,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 item = cx.single_element_list(args, cx.attr_span)?;
|
||||
let item = cx.expect_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;
|
||||
|
||||
@@ -311,11 +311,7 @@ pub(crate) fn parse_stability<S: Stage>(
|
||||
let mut feature = None;
|
||||
let mut since = None;
|
||||
|
||||
let ArgParser::List(list) = args else {
|
||||
let attr_span = cx.attr_span;
|
||||
cx.adcx().expected_list(attr_span, args);
|
||||
return None;
|
||||
};
|
||||
let list = cx.expect_list(args, cx.attr_span)?;
|
||||
|
||||
for param in list.mixed() {
|
||||
let param_span = param.span();
|
||||
@@ -383,11 +379,7 @@ pub(crate) fn parse_unstability<S: Stage>(
|
||||
let mut implied_by = None;
|
||||
let mut old_name = None;
|
||||
|
||||
let ArgParser::List(list) = args else {
|
||||
let attr_span = cx.attr_span;
|
||||
cx.adcx().expected_list(attr_span, args);
|
||||
return None;
|
||||
};
|
||||
let list = cx.expect_list(args, cx.attr_span)?;
|
||||
|
||||
for param in list.mixed() {
|
||||
let Some(param) = param.meta_item() else {
|
||||
@@ -503,11 +495,7 @@ fn extend(
|
||||
return None;
|
||||
}
|
||||
|
||||
let ArgParser::List(list) = args else {
|
||||
let attr_span = cx.attr_span;
|
||||
cx.adcx().expected_list(attr_span, args);
|
||||
return None;
|
||||
};
|
||||
let list = cx.expect_list(args, cx.attr_span)?;
|
||||
|
||||
for param in list.mixed() {
|
||||
let Some(param) = param.meta_item() else {
|
||||
|
||||
@@ -28,10 +28,11 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
|
||||
Some(str_value)
|
||||
}
|
||||
ArgParser::List(list) => {
|
||||
let help = list.single().and_then(|item| item.meta_item()).and_then(|item| {
|
||||
item.args().no_args().ok()?;
|
||||
Some(item.path().to_string())
|
||||
});
|
||||
let help =
|
||||
list.as_single().and_then(|item| item.meta_item()).and_then(|item| {
|
||||
item.args().no_args().ok()?;
|
||||
Some(item.path().to_string())
|
||||
});
|
||||
cx.adcx().warn_ill_formed_attribute_input_with_help(
|
||||
ILL_FORMED_ATTRIBUTE_INPUT,
|
||||
help,
|
||||
@@ -71,10 +72,7 @@ fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<Attrib
|
||||
Some(str_value)
|
||||
}
|
||||
ArgParser::List(list) => {
|
||||
let Some(single) = list.single() else {
|
||||
cx.adcx().expected_single_argument(list.span, list.len());
|
||||
return None;
|
||||
};
|
||||
let single = cx.expect_single(list)?;
|
||||
let Some(single) = single.meta_item() else {
|
||||
cx.adcx().expected_name_value(single.span(), Some(sym::expected));
|
||||
return None;
|
||||
@@ -140,17 +138,13 @@ impl<S: Stage> SingleAttributeParser<S> for RustcAbiParser {
|
||||
]);
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
|
||||
let Some(args) = args.list() else {
|
||||
let Some(args) = args.as_list() else {
|
||||
let attr_span = cx.attr_span;
|
||||
cx.adcx().expected_specific_argument_and_list(attr_span, &[sym::assert_eq, sym::debug]);
|
||||
return None;
|
||||
};
|
||||
|
||||
let Some(arg) = args.single() else {
|
||||
let attr_span = cx.attr_span;
|
||||
cx.adcx().expected_single_argument(attr_span, args.len());
|
||||
return None;
|
||||
};
|
||||
let arg = cx.expect_single(args)?;
|
||||
|
||||
let mut fail_incorrect_argument =
|
||||
|span| cx.adcx().expected_specific_argument(span, &[sym::assert_eq, sym::debug]);
|
||||
@@ -203,7 +197,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 single = cx.single_element_list(args, cx.attr_span)?;
|
||||
let single = cx.expect_single_element_list(args, cx.attr_span)?;
|
||||
|
||||
let Some(meta) = single.meta_item() else {
|
||||
cx.adcx().expected_not_literal(single.span());
|
||||
|
||||
@@ -17,11 +17,7 @@ impl<S: Stage> SingleAttributeParser<S> for RustcSkipDuringMethodDispatchParser
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
|
||||
let mut array = false;
|
||||
let mut boxed_slice = false;
|
||||
let Some(args) = args.list() else {
|
||||
let attr_span = cx.attr_span;
|
||||
cx.adcx().expected_list(attr_span, args);
|
||||
return None;
|
||||
};
|
||||
let args = cx.expect_list(args, cx.attr_span)?;
|
||||
if args.is_empty() {
|
||||
cx.adcx().expected_at_least_one_argument(args.span);
|
||||
return None;
|
||||
|
||||
@@ -41,7 +41,7 @@ pub(crate) fn parse_single_integer<S: Stage>(
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
args: &ArgParser,
|
||||
) -> Option<u128> {
|
||||
let single = cx.single_element_list(args, cx.attr_span)?;
|
||||
let single = cx.expect_single_element_list(args, cx.attr_span)?;
|
||||
let Some(lit) = single.lit() else {
|
||||
cx.adcx().expected_integer_literal(single.span());
|
||||
return None;
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
use crate::attributes::traits::*;
|
||||
use crate::attributes::transparency::*;
|
||||
use crate::attributes::{AttributeParser as _, AttributeSafety, Combine, Single, WithoutArgs};
|
||||
use crate::parser::{ArgParser, MetaItemOrLitParser, RefPathParser};
|
||||
use crate::parser::{ArgParser, MetaItemListParser, MetaItemOrLitParser, RefPathParser};
|
||||
use crate::session_diagnostics::{
|
||||
AttributeParseError, AttributeParseErrorReason, AttributeParseErrorSuggestions,
|
||||
ParsedDescription,
|
||||
@@ -554,7 +554,7 @@ pub(crate) fn adcx(&mut self) -> AttributeDiagnosticContext<'_, 'f, 'sess, S> {
|
||||
///
|
||||
/// 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>(
|
||||
pub(crate) fn expect_single_element_list<'arg>(
|
||||
&mut self,
|
||||
arg: &'arg ArgParser,
|
||||
span: Span,
|
||||
@@ -564,13 +564,36 @@ pub(crate) fn single_element_list<'arg>(
|
||||
return None;
|
||||
};
|
||||
|
||||
let Some(single) = l.single() else {
|
||||
let Some(single) = l.as_single() else {
|
||||
self.adcx().expected_single_argument(l.span, l.len());
|
||||
return None;
|
||||
};
|
||||
|
||||
Some(single)
|
||||
}
|
||||
|
||||
pub(crate) fn expect_list<'arg>(
|
||||
&mut self,
|
||||
args: &'arg ArgParser,
|
||||
span: Span,
|
||||
) -> Option<&'arg MetaItemListParser> {
|
||||
let list = args.as_list();
|
||||
if list.is_none() {
|
||||
self.adcx().expected_list(span, args);
|
||||
}
|
||||
list
|
||||
}
|
||||
|
||||
pub(crate) fn expect_single<'arg>(
|
||||
&mut self,
|
||||
list: &'arg MetaItemListParser,
|
||||
) -> Option<&'arg MetaItemOrLitParser> {
|
||||
let single = list.as_single();
|
||||
if single.is_none() {
|
||||
self.adcx().expected_single_argument(list.span, list.len());
|
||||
}
|
||||
single
|
||||
}
|
||||
}
|
||||
|
||||
impl<'f, 'sess, S: Stage> Deref for AcceptContext<'f, 'sess, S> {
|
||||
|
||||
@@ -176,7 +176,7 @@ pub fn from_attr_args<'sess>(
|
||||
///
|
||||
/// - `#[allow(clippy::complexity)]`: `(clippy::complexity)` is a list
|
||||
/// - `#[rustfmt::skip::macros(target_macro_name)]`: `(target_macro_name)` is a list
|
||||
pub fn list(&self) -> Option<&MetaItemListParser> {
|
||||
pub fn as_list(&self) -> Option<&MetaItemListParser> {
|
||||
match self {
|
||||
Self::List(l) => Some(l),
|
||||
Self::NameValue(_) | Self::NoArgs => None,
|
||||
@@ -694,7 +694,7 @@ pub fn is_empty(&self) -> bool {
|
||||
/// Returns Some if the list contains only a single element.
|
||||
///
|
||||
/// Inside the Some is the parser to parse this single element.
|
||||
pub fn single(&self) -> Option<&MetaItemOrLitParser> {
|
||||
pub fn as_single(&self) -> Option<&MetaItemOrLitParser> {
|
||||
let mut iter = self.mixed();
|
||||
iter.next().filter(|_| iter.next().is_none())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user