Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 06eb5a5

Browse files
Parsers for the attributes
Signed-off-by: Jonathan Brouwer <jonathantbrouwer@gmail.com>
1 parent 40df0e8 commit 06eb5a5

File tree

4 files changed

+161
-0
lines changed

4 files changed

+161
-0
lines changed

‎compiler/rustc_attr_parsing/src/attributes/mod.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ pub(crate) mod must_use;
3939
pub(crate) mod no_implicit_prelude;
4040
pub(crate) mod non_exhaustive;
4141
pub(crate) mod path;
42+
pub(crate) mod proc_macro_attrs;
4243
pub(crate) mod repr;
4344
pub(crate) mod rustc_internal;
4445
pub(crate) mod semantics;
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
use rustc_attr_data_structures::AttributeKind;
2+
use rustc_feature::{AttributeTemplate, template};
3+
use rustc_span::{Span, Symbol, sym};
4+
use thin_vec::ThinVec;
5+
6+
use crate::attributes::{
7+
AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
8+
};
9+
use crate::context::{AcceptContext, Stage};
10+
use crate::parser::ArgParser;
11+
12+
pub(crate) struct ProcMacroParser;
13+
impl<S: Stage> NoArgsAttributeParser<S> for ProcMacroParser {
14+
const PATH: &[Symbol] = &[sym::proc_macro];
15+
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
16+
const CREATE: fn(Span) -> AttributeKind = AttributeKind::ProcMacro;
17+
}
18+
19+
pub(crate) struct ProcMacroAttributeParser;
20+
impl<S: Stage> NoArgsAttributeParser<S> for ProcMacroAttributeParser {
21+
const PATH: &[Symbol] = &[sym::proc_macro_attribute];
22+
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
23+
const CREATE: fn(Span) -> AttributeKind = AttributeKind::ProcMacroAttribute;
24+
}
25+
26+
pub(crate) struct ProcMacroDeriveParser;
27+
impl<S: Stage> SingleAttributeParser<S> for ProcMacroDeriveParser {
28+
const PATH: &[Symbol] = &[sym::proc_macro_derive];
29+
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
30+
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
31+
const TEMPLATE: AttributeTemplate =
32+
template!(List: "TraitName, /*opt*/ attributes(name1, name2, ...)");
33+
34+
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
35+
let (trait_name, helper_attrs) = parse_derive_like(cx, args, true)?;
36+
Some(AttributeKind::ProcMacroDerive {
37+
trait_name: trait_name.expect("Trait name is mandatory, so it is present"),
38+
helper_attrs,
39+
span: cx.attr_span,
40+
})
41+
}
42+
}
43+
44+
pub(crate) struct RustcBuiltinMacroParser;
45+
impl<S: Stage> SingleAttributeParser<S> for RustcBuiltinMacroParser {
46+
const PATH: &[Symbol] = &[sym::rustc_builtin_macro];
47+
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
48+
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
49+
const TEMPLATE: AttributeTemplate =
50+
template!(List: "TraitName, /*opt*/ attributes(name1, name2, ...)");
51+
52+
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
53+
let (builtin_name, helper_attrs) = parse_derive_like(cx, args, false)?;
54+
Some(AttributeKind::RustcBuiltinMacro { builtin_name, helper_attrs, span: cx.attr_span })
55+
}
56+
}
57+
58+
fn parse_derive_like<S: Stage>(
59+
cx: &mut AcceptContext<'_, '_, S>,
60+
args: &ArgParser<'_>,
61+
trait_name_mandatory: bool,
62+
) -> Option<(Option<Symbol>, ThinVec<Symbol>)> {
63+
let Some(list) = args.list() else {
64+
cx.expected_list(cx.attr_span);
65+
return None;
66+
};
67+
let mut items = list.mixed();
68+
69+
// Parse the name of the trait that is derived.
70+
let Some(trait_attr) = items.next() else {
71+
// For #[rustc_builtin_macro], it is permitted to leave out the trait name
72+
if !trait_name_mandatory {
73+
return None;
74+
}
75+
cx.expected_at_least_one_argument(list.span);
76+
return None;
77+
};
78+
let Some(trait_attr) = trait_attr.meta_item() else {
79+
cx.unexpected_literal(trait_attr.span());
80+
return None;
81+
};
82+
let Some(trait_ident) = trait_attr.path().word() else {
83+
cx.expected_identifier(trait_attr.path().span());
84+
return None;
85+
};
86+
if !trait_ident.name.can_be_raw() {
87+
cx.expected_identifier(trait_ident.span);
88+
return None;
89+
}
90+
if let Err(e) = trait_attr.args().no_args() {
91+
cx.expected_no_args(e);
92+
return None;
93+
};
94+
95+
// Parse optional attributes
96+
let mut attributes = ThinVec::new();
97+
if let Some(attrs) = items.next() {
98+
let Some(attr_list) = attrs.meta_item() else {
99+
cx.expected_list(attrs.span());
100+
return None;
101+
};
102+
if !attr_list.path().word_is(sym::attributes) {
103+
cx.expected_specific_argument(attrs.span(), vec!["attributes"]);
104+
return None;
105+
}
106+
let Some(attr_list) = attr_list.args().list() else {
107+
cx.expected_list(attrs.span());
108+
return None;
109+
};
110+
111+
// Parse item in `attributes(...)` argument
112+
for attr in attr_list.mixed() {
113+
let Some(attr) = attr.meta_item() else {
114+
cx.expected_identifier(attr.span());
115+
return None;
116+
};
117+
if let Err(e) = attr.args().no_args() {
118+
cx.expected_no_args(e);
119+
return None;
120+
};
121+
let Some(ident) = attr.path().word() else {
122+
cx.expected_identifier(attr.path().span());
123+
return None;
124+
};
125+
if !ident.name.can_be_raw() {
126+
cx.expected_identifier(ident.span);
127+
return None;
128+
}
129+
attributes.push(ident.name);
130+
}
131+
}
132+
133+
// If anything else is specified, we should reject it
134+
if let Some(next) = items.next() {
135+
cx.expected_no_args(next.span());
136+
}
137+
138+
Some((Some(trait_ident.name), attributes))
139+
}

‎compiler/rustc_attr_parsing/src/context.rs‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ use crate::attributes::must_use::MustUseParser;
3333
use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser;
3434
use crate::attributes::non_exhaustive::NonExhaustiveParser;
3535
use crate::attributes::path::PathParser as PathAttributeParser;
36+
use crate::attributes::proc_macro_attrs::{
37+
ProcMacroAttributeParser, ProcMacroDeriveParser, ProcMacroParser, RustcBuiltinMacroParser,
38+
};
3639
use crate::attributes::repr::{AlignParser, ReprParser};
3740
use crate::attributes::rustc_internal::{
3841
RustcLayoutScalarValidRangeEnd, RustcLayoutScalarValidRangeStart,
@@ -140,6 +143,8 @@ attribute_parsers!(
140143
Single<MustUseParser>,
141144
Single<OptimizeParser>,
142145
Single<PathAttributeParser>,
146+
Single<ProcMacroDeriveParser>,
147+
Single<RustcBuiltinMacroParser>,
143148
Single<RustcForceInlineParser>,
144149
Single<RustcLayoutScalarValidRangeEnd>,
145150
Single<RustcLayoutScalarValidRangeStart>,
@@ -159,6 +164,8 @@ attribute_parsers!(
159164
Single<WithoutArgs<NoMangleParser>>,
160165
Single<WithoutArgs<NonExhaustiveParser>>,
161166
Single<WithoutArgs<PassByValueParser>>,
167+
Single<WithoutArgs<ProcMacroAttributeParser>>,
168+
Single<WithoutArgs<ProcMacroParser>>,
162169
Single<WithoutArgs<PubTransparentParser>>,
163170
Single<WithoutArgs<StdInternalSymbolParser>>,
164171
Single<WithoutArgs<TrackCallerParser>>,
@@ -427,6 +434,16 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
427434
})
428435
}
429436

437+
pub(crate) fn expected_identifier(&self, span: Span) -> ErrorGuaranteed {
438+
self.emit_err(AttributeParseError {
439+
span,
440+
attr_span: self.attr_span,
441+
template: self.template.clone(),
442+
attribute: self.attr_path.clone(),
443+
reason: AttributeParseErrorReason::ExpectedIdentifier,
444+
})
445+
}
446+
430447
pub(crate) fn warn_empty_attribute(&mut self, span: Span) {
431448
self.emit_lint(AttributeLintKind::EmptyAttribute { first_span: span }, span);
432449
}

‎compiler/rustc_attr_parsing/src/session_diagnostics.rs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,7 @@ pub(crate) enum AttributeParseErrorReason {
525525
ExpectedNameValue(Option<Symbol>),
526526
DuplicateKey(Symbol),
527527
ExpectedSpecificArgument { possibilities: Vec<&'static str>, strings: bool },
528+
ExpectedIdentifier,
528529
}
529530

530531
pub(crate) struct AttributeParseError {
@@ -618,6 +619,9 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError {
618619
}
619620
}
620621
}
622+
AttributeParseErrorReason::ExpectedIdentifier => {
623+
diag.span_label(self.span, format!("expected a valid identifier here"));
624+
}
621625
}
622626

623627
let suggestions = self.template.suggestions(false, &name);

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /