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 6bd3273

Browse files
Rollup merge of #143607 - JonathanBrouwer:proc_macro_attrs, r=jdonszelmann,traviscross
Port the proc macro attributes to the new attribute parsing infrastructure Ports `#[proc_macro]`, `#[proc_macro_attribute]`, `#[proc_macro_derive]` and `#[rustc_builtin_macro]` to the new attribute parsing infrastructure for #131229 (comment) I've split this PR into commits for reviewability, and left some comments to clarify things I did 4 related attributes in one PR because they share a lot of their code and logic, and doing them separately is kind of annoying as I need to leave both the old and new parsing in place then. r? ``@oli-obk`` cc ``@jdonszelmann``
2 parents f8e355c + 97b6521 commit 6bd3273

File tree

26 files changed

+520
-393
lines changed

26 files changed

+520
-393
lines changed

‎compiler/rustc_attr_data_structures/src/attributes.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,12 +416,24 @@ pub enum AttributeKind {
416416
/// Represents `#[pointee]`
417417
Pointee(Span),
418418

419+
/// Represents `#[proc_macro]`
420+
ProcMacro(Span),
421+
422+
/// Represents `#[proc_macro_attribute]`
423+
ProcMacroAttribute(Span),
424+
425+
/// Represents `#[proc_macro_derive]`
426+
ProcMacroDerive { trait_name: Symbol, helper_attrs: ThinVec<Symbol>, span: Span },
427+
419428
/// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint).
420429
PubTransparent(Span),
421430

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

434+
/// Represents `#[rustc_builtin_macro]`.
435+
RustcBuiltinMacro { builtin_name: Option<Symbol>, helper_attrs: ThinVec<Symbol>, span: Span },
436+
425437
/// Represents `#[rustc_layout_scalar_valid_range_end]`.
426438
RustcLayoutScalarValidRangeEnd(Box<u128>, Span),
427439

‎compiler/rustc_attr_data_structures/src/encode_cross_crate.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,12 @@ impl AttributeKind {
6161
PassByValue(..) => Yes,
6262
Path(..) => No,
6363
Pointee(..) => No,
64+
ProcMacro(..) => No,
65+
ProcMacroAttribute(..) => No,
66+
ProcMacroDerive { .. } => No,
6467
PubTransparent(..) => Yes,
6568
Repr { .. } => No,
69+
RustcBuiltinMacro { .. } => Yes,
6670
RustcLayoutScalarValidRangeEnd(..) => Yes,
6771
RustcLayoutScalarValidRangeStart(..) => Yes,
6872
RustcObjectLifetimeDefault => No,

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ pub(crate) mod must_use;
4141
pub(crate) mod no_implicit_prelude;
4242
pub(crate) mod non_exhaustive;
4343
pub(crate) mod path;
44+
pub(crate) mod proc_macro_attrs;
4445
pub(crate) mod repr;
4546
pub(crate) mod rustc_internal;
4647
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+
// For #[rustc_builtin_macro], it is permitted to leave out the trait name
65+
if args.no_args().is_ok() && !trait_name_mandatory {
66+
return Some((None, ThinVec::new()));
67+
}
68+
cx.expected_list(cx.attr_span);
69+
return None;
70+
};
71+
let mut items = list.mixed();
72+
73+
// Parse the name of the trait that is derived.
74+
let Some(trait_attr) = items.next() else {
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: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ use crate::attributes::must_use::MustUseParser;
3838
use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser;
3939
use crate::attributes::non_exhaustive::NonExhaustiveParser;
4040
use crate::attributes::path::PathParser as PathAttributeParser;
41+
use crate::attributes::proc_macro_attrs::{
42+
ProcMacroAttributeParser, ProcMacroDeriveParser, ProcMacroParser, RustcBuiltinMacroParser,
43+
};
4144
use crate::attributes::repr::{AlignParser, ReprParser};
4245
use crate::attributes::rustc_internal::{
4346
RustcLayoutScalarValidRangeEnd, RustcLayoutScalarValidRangeStart,
@@ -154,6 +157,8 @@ attribute_parsers!(
154157
Single<MustUseParser>,
155158
Single<OptimizeParser>,
156159
Single<PathAttributeParser>,
160+
Single<ProcMacroDeriveParser>,
161+
Single<RustcBuiltinMacroParser>,
157162
Single<RustcForceInlineParser>,
158163
Single<RustcLayoutScalarValidRangeEnd>,
159164
Single<RustcLayoutScalarValidRangeStart>,
@@ -186,6 +191,8 @@ attribute_parsers!(
186191
Single<WithoutArgs<ParenSugarParser>>,
187192
Single<WithoutArgs<PassByValueParser>>,
188193
Single<WithoutArgs<PointeeParser>>,
194+
Single<WithoutArgs<ProcMacroAttributeParser>>,
195+
Single<WithoutArgs<ProcMacroParser>>,
189196
Single<WithoutArgs<PubTransparentParser>>,
190197
Single<WithoutArgs<SpecializationTraitParser>>,
191198
Single<WithoutArgs<StdInternalSymbolParser>>,

‎compiler/rustc_builtin_macros/src/proc_macro_harness.rs

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
use std::mem;
1+
use std::{mem, slice};
22

33
use rustc_ast::ptr::P;
44
use rustc_ast::visit::{self, Visitor};
5-
use rustc_ast::{self as ast, NodeId, attr};
5+
use rustc_ast::{self as ast, HasNodeId,NodeId, attr};
66
use rustc_ast_pretty::pprust;
7+
use rustc_attr_data_structures::AttributeKind;
8+
use rustc_attr_parsing::AttributeParser;
79
use rustc_errors::DiagCtxtHandle;
8-
use rustc_expand::base::{ExtCtxt, ResolverExpand, parse_macro_name_and_helper_attrs};
10+
use rustc_expand::base::{ExtCtxt, ResolverExpand};
911
use rustc_expand::expand::{AstFragment, ExpansionConfig};
1012
use rustc_feature::Features;
1113
use rustc_session::Session;
@@ -22,7 +24,7 @@ struct ProcMacroDerive {
2224
trait_name: Symbol,
2325
function_ident: Ident,
2426
span: Span,
25-
attrs: Vec<Symbol>,
27+
attrs: ThinVec<Symbol>,
2628
}
2729

2830
struct ProcMacroDef {
@@ -41,6 +43,7 @@ struct CollectProcMacros<'a> {
4143
macros: Vec<ProcMacro>,
4244
in_root: bool,
4345
dcx: DiagCtxtHandle<'a>,
46+
session: &'a Session,
4447
source_map: &'a SourceMap,
4548
is_proc_macro_crate: bool,
4649
is_test_crate: bool,
@@ -63,6 +66,7 @@ pub fn inject(
6366
macros: Vec::new(),
6467
in_root: true,
6568
dcx,
69+
session: sess,
6670
source_map: sess.source_map(),
6771
is_proc_macro_crate,
6872
is_test_crate,
@@ -98,8 +102,18 @@ impl<'a> CollectProcMacros<'a> {
98102
function_ident: Ident,
99103
attr: &'a ast::Attribute,
100104
) {
101-
let Some((trait_name, proc_attrs)) =
102-
parse_macro_name_and_helper_attrs(self.dcx, attr, "derive")
105+
let Some(rustc_hir::Attribute::Parsed(AttributeKind::ProcMacroDerive {
106+
trait_name,
107+
helper_attrs,
108+
..
109+
})) = AttributeParser::parse_limited(
110+
self.session,
111+
slice::from_ref(attr),
112+
sym::proc_macro_derive,
113+
item.span,
114+
item.node_id(),
115+
None,
116+
)
103117
else {
104118
return;
105119
};
@@ -110,7 +124,7 @@ impl<'a> CollectProcMacros<'a> {
110124
span: item.span,
111125
trait_name,
112126
function_ident,
113-
attrs: proc_attrs,
127+
attrs: helper_attrs,
114128
}));
115129
} else {
116130
let msg = if !self.in_root {

‎compiler/rustc_expand/messages.ftl

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,8 @@
1-
expand_arg_not_attributes =
2-
second argument must be `attributes`
3-
4-
expand_attr_no_arguments =
5-
attribute must have either one or two arguments
6-
7-
expand_attribute_meta_item =
8-
attribute must be a meta item, not a literal
9-
10-
expand_attribute_single_word =
11-
attribute must only be a single word
12-
131
expand_attributes_on_expressions_experimental =
142
attributes on expressions are experimental
153
.help_outer_doc = `///` is used for outer documentation comments; for a plain comment, use `//`
164
.help_inner_doc = `//!` is used for inner documentation comments; for a plain comment, use `//` by removing the `!` or inserting a space in between them: `// !`
175
18-
expand_attributes_wrong_form =
19-
attribute must be of form: `attributes(foo, bar)`
20-
21-
expand_cannot_be_name_of_macro =
22-
`{$trait_ident}` cannot be a name of {$macro_type} macro
23-
246
expand_collapse_debuginfo_illegal =
257
illegal value for attribute #[collapse_debuginfo(no|external|yes)]
268
@@ -71,9 +53,6 @@ expand_glob_delegation_outside_impls =
7153
expand_glob_delegation_traitless_qpath =
7254
qualified path without a trait in glob delegation
7355
74-
expand_helper_attribute_name_invalid =
75-
`{$name}` cannot be a name of derive helper attribute
76-
7756
expand_incomplete_parse =
7857
macro expansion ignores {$descr} and any tokens following
7958
.label = caused by the macro expansion here
@@ -165,12 +144,6 @@ expand_mve_unrecognized_var =
165144
expand_non_inline_modules_in_proc_macro_input_are_unstable =
166145
non-inline modules in proc macro input are unstable
167146
168-
expand_not_a_meta_item =
169-
not a meta item
170-
171-
expand_only_one_word =
172-
must only be one word
173-
174147
expand_proc_macro_back_compat = using an old version of `{$crate_name}`
175148
.note = older versions of the `{$crate_name}` crate no longer compile; please update to `{$crate_name}` v{$fixed_version}, or switch to one of the `{$crate_name}` alternatives
176149

0 commit comments

Comments
(0)

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