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 7b23769

Browse files
Implement the proc macro attributes to the new attribute parsing infrastructure
1 parent 8df4a58 commit 7b23769

File tree

7 files changed

+195
-11
lines changed

7 files changed

+195
-11
lines changed

‎compiler/rustc_attr_data_structures/src/attributes.rs‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,12 +301,24 @@ pub enum AttributeKind {
301301
/// Represents `#[path]`
302302
Path(Symbol, Span),
303303

304+
/// Represents `#[proc_macro]`
305+
ProcMacro(Span),
306+
307+
/// Represents `#[proc_macro_attribute]`
308+
ProcMacroAttribute(Span),
309+
310+
/// Represents `#[proc_macro_derive]`
311+
ProcMacroDerive { trait_name: Symbol, helper_attrs: ThinVec<Symbol>, span: Span },
312+
304313
/// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint).
305314
PubTransparent(Span),
306315

307316
/// Represents [`#[repr]`](https://doc.rust-lang.org/stable/reference/type-layout.html#representations).
308317
Repr { reprs: ThinVec<(ReprAttr, Span)>, first_span: Span },
309318

319+
/// Represents `#[rustc_builtin_macro]`.
320+
RustcBuiltinMacro { builtin_name: Option<Symbol>, helper_attrs: ThinVec<Symbol>, span: Span },
321+
310322
/// Represents `#[rustc_layout_scalar_valid_range_end]`.
311323
RustcLayoutScalarValidRangeEnd(Box<u128>, Span),
312324

‎compiler/rustc_attr_data_structures/src/encode_cross_crate.rs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,12 @@ impl AttributeKind {
4141
Optimize(..) => No,
4242
PassByValue(..) => Yes,
4343
Path(..) => No,
44+
ProcMacro(..) => No,
45+
ProcMacroAttribute(..) => No,
46+
ProcMacroDerive { .. } => No,
4447
PubTransparent(..) => Yes,
4548
Repr { .. } => No,
49+
RustcBuiltinMacro { .. } => Yes,
4650
RustcLayoutScalarValidRangeEnd(..) => Yes,
4751
RustcLayoutScalarValidRangeStart(..) => Yes,
4852
RustcObjectLifetimeDefault => No,

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ pub(crate) mod must_use;
3838
pub(crate) mod no_implicit_prelude;
3939
pub(crate) mod non_exhaustive;
4040
pub(crate) mod path;
41+
pub(crate) mod proc_macro_attrs;
4142
pub(crate) mod repr;
4243
pub(crate) mod rustc_internal;
4344
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::KeepLast;
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::KeepLast;
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
@@ -29,6 +29,9 @@ use crate::attributes::must_use::MustUseParser;
2929
use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser;
3030
use crate::attributes::non_exhaustive::NonExhaustiveParser;
3131
use crate::attributes::path::PathParser as PathAttributeParser;
32+
use crate::attributes::proc_macro_attrs::{
33+
ProcMacroAttributeParser, ProcMacroDeriveParser, ProcMacroParser, RustcBuiltinMacroParser,
34+
};
3235
use crate::attributes::repr::{AlignParser, ReprParser};
3336
use crate::attributes::rustc_internal::{
3437
RustcLayoutScalarValidRangeEnd, RustcLayoutScalarValidRangeStart,
@@ -135,6 +138,8 @@ attribute_parsers!(
135138
Single<MustUseParser>,
136139
Single<OptimizeParser>,
137140
Single<PathAttributeParser>,
141+
Single<ProcMacroDeriveParser>,
142+
Single<RustcBuiltinMacroParser>,
138143
Single<RustcForceInlineParser>,
139144
Single<RustcLayoutScalarValidRangeEnd>,
140145
Single<RustcLayoutScalarValidRangeStart>,
@@ -151,6 +156,8 @@ attribute_parsers!(
151156
Single<WithoutArgs<NoMangleParser>>,
152157
Single<WithoutArgs<NonExhaustiveParser>>,
153158
Single<WithoutArgs<PassByValueParser>>,
159+
Single<WithoutArgs<ProcMacroAttributeParser>>,
160+
Single<WithoutArgs<ProcMacroParser>>,
154161
Single<WithoutArgs<PubTransparentParser>>,
155162
Single<WithoutArgs<TrackCallerParser>>,
156163
// tidy-alphabetical-end
@@ -418,6 +425,16 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
418425
})
419426
}
420427

428+
pub(crate) fn expected_identifier(&self, span: Span) -> ErrorGuaranteed {
429+
self.emit_err(AttributeParseError {
430+
span,
431+
attr_span: self.attr_span,
432+
template: self.template.clone(),
433+
attribute: self.attr_path.clone(),
434+
reason: AttributeParseErrorReason::ExpectedIdentifier,
435+
})
436+
}
437+
421438
pub(crate) fn warn_empty_attribute(&mut self, span: Span) {
422439
self.emit_lint(AttributeLintKind::EmptyAttribute { first_span: span }, span);
423440
}

‎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);

‎compiler/rustc_passes/src/check_attr.rs‎

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,22 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
120120
for attr in attrs {
121121
let mut style = None;
122122
match attr {
123+
Attribute::Parsed(AttributeKind::ProcMacro(_)) => {
124+
self.check_proc_macro(hir_id, target, ProcMacroKind::FunctionLike)
125+
}
126+
Attribute::Parsed(AttributeKind::ProcMacroAttribute(_)) => {
127+
self.check_proc_macro(hir_id, target, ProcMacroKind::Attribute);
128+
}
129+
Attribute::Parsed(AttributeKind::ProcMacroDerive { span: attr_span, .. }) => {
130+
self.check_generic_attr(
131+
hir_id,
132+
sym::proc_macro_derive,
133+
*attr_span,
134+
target,
135+
Target::Fn,
136+
);
137+
self.check_proc_macro(hir_id, target, ProcMacroKind::Derive)
138+
}
123139
Attribute::Parsed(AttributeKind::SkipDuringMethodDispatch {
124140
span: attr_span,
125141
..
@@ -207,7 +223,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
207223
Attribute::Parsed(
208224
AttributeKind::BodyStability { .. }
209225
| AttributeKind::ConstStabilityIndirect
210-
| AttributeKind::MacroTransparency(_),
226+
| AttributeKind::MacroTransparency(_)
227+
| AttributeKind::RustcBuiltinMacro { .. },
211228
) => { /* do nothing */ }
212229
Attribute::Parsed(AttributeKind::AsPtr(attr_span)) => {
213230
self.check_applied_to_fn_or_method(hir_id, *attr_span, span, target)
@@ -315,16 +332,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
315332
[sym::automatically_derived, ..] => {
316333
self.check_generic_attr_unparsed(hir_id, attr, target, Target::Impl)
317334
}
318-
[sym::proc_macro, ..] => {
319-
self.check_proc_macro(hir_id, target, ProcMacroKind::FunctionLike)
320-
}
321-
[sym::proc_macro_attribute, ..] => {
322-
self.check_proc_macro(hir_id, target, ProcMacroKind::Attribute);
323-
}
324-
[sym::proc_macro_derive, ..] => {
325-
self.check_generic_attr_unparsed(hir_id, attr, target, Target::Fn);
326-
self.check_proc_macro(hir_id, target, ProcMacroKind::Derive)
327-
}
328335
[sym::autodiff_forward, ..] | [sym::autodiff_reverse, ..] => {
329336
self.check_autodiff(hir_id, attr, span, target)
330337
}

0 commit comments

Comments
(0)

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