Skip to content

Commit e819bed

Browse files
committed
[DISCUSSIONS NEEDED] Add a simpler, harder to misuse, attribute parsing API
1 parent 827651f commit e819bed

10 files changed

Lines changed: 41 additions & 77 deletions

File tree

compiler/rustc_attr_parsing/src/attributes/cfg.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,7 @@ pub fn parse_cfg<S: Stage>(
4444
cx: &mut AcceptContext<'_, '_, S>,
4545
args: &ArgParser,
4646
) -> Option<CfgEntry> {
47-
let ArgParser::List(list) = args else {
48-
let attr_span = cx.attr_span;
49-
cx.adcx().expected_list(attr_span, args);
50-
return None;
51-
};
47+
let list = cx.list(args, cx.attr_span)?;
5248

5349
let Some(single) = list.single() else {
5450
let target = cx.target;

compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -588,11 +588,7 @@ impl<S: Stage> SingleAttributeParser<S> for SanitizeParser {
588588
]);
589589

590590
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
591-
let Some(list) = args.list() else {
592-
let attr_span = cx.attr_span;
593-
cx.adcx().expected_list(attr_span, args);
594-
return None;
595-
};
591+
let list = cx.list(args, cx.attr_span)?;
596592

597593
let mut on_set = SanitizerSet::empty();
598594
let mut off_set = SanitizerSet::empty();
@@ -719,11 +715,7 @@ impl<S: Stage> SingleAttributeParser<S> for PatchableFunctionEntryParser {
719715
const TEMPLATE: AttributeTemplate = template!(List: &["prefix_nops = m, entry_nops = n"]);
720716

721717
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
722-
let Some(meta_item_list) = args.list() else {
723-
let attr_span = cx.attr_span;
724-
cx.adcx().expected_list(attr_span, args);
725-
return None;
726-
};
718+
let meta_item_list = cx.list(args, cx.attr_span)?;
727719

728720
let mut prefix = None;
729721
let mut entry = None;

compiler/rustc_attr_parsing/src/attributes/confusables.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,7 @@ impl<S: Stage> AttributeParser<S> for ConfusablesParser {
1212
&[sym::rustc_confusables],
1313
template!(List: &[r#""name1", "name2", ..."#]),
1414
|this, cx, args| {
15-
let Some(list) = args.list() else {
16-
let attr_span = cx.attr_span;
17-
cx.adcx().expected_list(attr_span, args);
18-
return;
19-
};
15+
let Some(list) = cx.list(args, cx.attr_span) else { return };
2016

2117
if list.is_empty() {
2218
cx.emit_err(EmptyConfusables { span: cx.attr_span });

compiler/rustc_attr_parsing/src/attributes/inline.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,7 @@ impl<S: Stage> SingleAttributeParser<S> for InlineParser {
3737
match args {
3838
ArgParser::NoArgs => Some(AttributeKind::Inline(InlineAttr::Hint, cx.attr_span)),
3939
ArgParser::List(list) => {
40-
let Some(l) = list.single() else {
41-
cx.adcx().expected_single_argument(list.span, list.len());
42-
return None;
43-
};
40+
let l = cx.single(list)?;
4441

4542
match l.meta_item().and_then(|i| i.path().word_sym()) {
4643
Some(sym::always) => {
@@ -78,10 +75,7 @@ impl<S: Stage> SingleAttributeParser<S> for RustcForceInlineParser {
7875
let reason = match args {
7976
ArgParser::NoArgs => None,
8077
ArgParser::List(list) => {
81-
let Some(l) = list.single() else {
82-
cx.adcx().expected_single_argument(list.span, list.len());
83-
return None;
84-
};
78+
let l = cx.single(list)?;
8579

8680
let Some(reason) = l.lit().and_then(|i| i.kind.str()) else {
8781
cx.adcx().expected_string_literal(l.span(), l.lit());

compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,7 @@ fn parse_derive_like<S: Stage>(
101101
cx.adcx().expected_specific_argument(attrs.span(), &[sym::attributes]);
102102
return None;
103103
}
104-
let Some(attr_list) = attr_list.args().list() else {
105-
cx.adcx().expected_list(attrs.span(), attr_list.args());
106-
return None;
107-
};
104+
let attr_list = cx.list(attr_list.args(), attrs.span())?;
108105

109106
// Parse item in `attributes(...)` argument
110107
for attr in attr_list.mixed() {

compiler/rustc_attr_parsing/src/attributes/prototype.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,7 @@ impl<S: Stage> SingleAttributeParser<S> for CustomMirParser {
2222
const TEMPLATE: AttributeTemplate = template!(List: &[r#"dialect = "...", phase = "...""#]);
2323

2424
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
25-
let Some(list) = args.list() else {
26-
let attr_span = cx.attr_span;
27-
cx.adcx().expected_list(attr_span, args);
28-
return None;
29-
};
25+
let list = cx.list(args, cx.attr_span)?;
3026

3127
let mut dialect = None;
3228
let mut phase = None;

compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,7 @@ impl<S: Stage> SingleAttributeParser<S> for RustcMustImplementOneOfParser {
3030
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
3131
const TEMPLATE: AttributeTemplate = template!(List: &["function1, function2, ..."]);
3232
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
33-
let Some(list) = args.list() else {
34-
let span = cx.attr_span;
35-
cx.adcx().expected_list(span, args);
36-
return None;
37-
};
33+
let list = cx.list(args, cx.attr_span)?;
3834

3935
let mut fn_names = ThinVec::new();
4036

@@ -210,11 +206,7 @@ fn parse_cgu_fields<S: Stage>(
210206
args: &ArgParser,
211207
accepts_kind: bool,
212208
) -> Option<(Symbol, Symbol, Option<CguKind>)> {
213-
let Some(args) = args.list() else {
214-
let attr_span = cx.attr_span;
215-
cx.adcx().expected_list(attr_span, args);
216-
return None;
217-
};
209+
let args = cx.list(args, cx.attr_span)?;
218210

219211
let mut cfg = None::<(Symbol, Span)>;
220212
let mut module = None::<(Symbol, Span)>;
@@ -418,11 +410,7 @@ impl<S: Stage> SingleAttributeParser<S> for RustcNeverTypeOptionsParser {
418410
]);
419411

420412
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
421-
let Some(list) = args.list() else {
422-
let attr_span = cx.attr_span;
423-
cx.adcx().expected_list(attr_span, args);
424-
return None;
425-
};
413+
let list = cx.list(args, cx.attr_span)?;
426414

427415
let mut fallback = None::<Ident>;
428416
let mut diverging_block_default = None::<Ident>;
@@ -825,11 +813,8 @@ impl<S: Stage> CombineAttributeParser<S> for RustcCleanParser {
825813
if !cx.cx.sess.opts.unstable_opts.query_dep_graph {
826814
cx.emit_err(AttributeRequiresOpt { span: cx.attr_span, opt: "-Z query-dep-graph" });
827815
}
828-
let Some(list) = args.list() else {
829-
let attr_span = cx.attr_span;
830-
cx.adcx().expected_list(attr_span, args);
831-
return None;
832-
};
816+
let list = cx.list(args, cx.attr_span)?;
817+
833818
let mut except = None;
834819
let mut loaded_from_disk = None;
835820
let mut cfg = None;
@@ -926,11 +911,7 @@ impl<S: Stage> SingleAttributeParser<S> for RustcIfThisChangedParser {
926911
match args {
927912
ArgParser::NoArgs => Some(AttributeKind::RustcIfThisChanged(cx.attr_span, None)),
928913
ArgParser::List(list) => {
929-
let Some(item) = list.single() else {
930-
let attr_span = cx.attr_span;
931-
cx.adcx().expected_single_argument(attr_span, list.len());
932-
return None;
933-
};
914+
let item = cx.single(list)?;
934915
let Some(ident) = item.meta_item().and_then(|item| item.ident()) else {
935916
cx.adcx().expected_identifier(item.span());
936917
return None;

compiler/rustc_attr_parsing/src/attributes/test_attrs.rs

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,7 @@ impl<S: Stage> SingleAttributeParser<S> for ShouldPanicParser {
7171
Some(str_value)
7272
}
7373
ArgParser::List(list) => {
74-
let Some(single) = list.single() else {
75-
cx.adcx().expected_single_argument(list.span, list.len());
76-
return None;
77-
};
74+
let single = cx.single(list)?;
7875
let Some(single) = single.meta_item() else {
7976
cx.adcx().expected_name_value(single.span(), Some(sym::expected));
8077
return None;
@@ -146,11 +143,7 @@ impl<S: Stage> SingleAttributeParser<S> for RustcAbiParser {
146143
return None;
147144
};
148145

149-
let Some(arg) = args.single() else {
150-
let attr_span = cx.attr_span;
151-
cx.adcx().expected_single_argument(attr_span, args.len());
152-
return None;
153-
};
146+
let arg = cx.single(args)?;
154147

155148
let mut fail_incorrect_argument =
156149
|span| cx.adcx().expected_specific_argument(span, &[sym::assert_eq, sym::debug]);

compiler/rustc_attr_parsing/src/attributes/traits.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,7 @@ impl<S: Stage> SingleAttributeParser<S> for RustcSkipDuringMethodDispatchParser
1717
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
1818
let mut array = false;
1919
let mut boxed_slice = false;
20-
let Some(args) = args.list() else {
21-
let attr_span = cx.attr_span;
22-
cx.adcx().expected_list(attr_span, args);
23-
return None;
24-
};
20+
let args = cx.list(args, cx.attr_span)?;
2521
if args.is_empty() {
2622
cx.adcx().expected_at_least_one_argument(args.span);
2723
return None;

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ use crate::attributes::test_attrs::*;
6161
use crate::attributes::traits::*;
6262
use crate::attributes::transparency::*;
6363
use crate::attributes::{AttributeParser as _, AttributeSafety, Combine, Single, WithoutArgs};
64-
use crate::parser::{ArgParser, MetaItemOrLitParser, RefPathParser};
64+
use crate::parser::{ArgParser, MetaItemListParser, MetaItemOrLitParser, RefPathParser};
6565
use crate::session_diagnostics::{
6666
AttributeParseError, AttributeParseErrorReason, AttributeParseErrorSuggestions,
6767
ParsedDescription,
@@ -571,6 +571,29 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
571571

572572
Some(single)
573573
}
574+
575+
pub(crate) fn list<'arg>(
576+
&mut self,
577+
args: &'arg ArgParser,
578+
span: Span,
579+
) -> Option<&'arg MetaItemListParser> {
580+
let list = args.list();
581+
if list.is_none() {
582+
self.adcx().expected_list(span, args);
583+
}
584+
list
585+
}
586+
587+
pub(crate) fn single<'arg>(
588+
&mut self,
589+
list: &'arg MetaItemListParser,
590+
) -> Option<&'arg MetaItemOrLitParser> {
591+
let single = list.single();
592+
if single.is_none() {
593+
self.adcx().expected_single_argument(list.span, list.len());
594+
}
595+
single
596+
}
574597
}
575598

576599
impl<'f, 'sess, S: Stage> Deref for AcceptContext<'f, 'sess, S> {

0 commit comments

Comments
 (0)