proc_macro_api/
lib.rs

1#![doc = include_str!("../doc.md")]
2#![no_std]
3
4/*
5checklist:
6 tt, ident, expr ;
7 doc_hidden macro_export `pma` ;
8 comma attr `#,` matcher: "$($at:tt),*" | "$(, $at:tt)*" | ...
9 path $crate::`pma`! ;
10 path $crate::__private ;
11 path "\$crate::(\w+::)*\w+!\s*(?=[\(\{\[])", "\w+\s*!\s*(?=[\(\{\[])"
12*/
13
14extern crate proc_macro;
15
16#[doc(hidden)]
17pub mod __private;
18
19mod err_syn;
20mod fmt;
21
22/// See the [crate documentation][self].
23#[macro_export]
24macro_rules! proc_macro_api {
25    ($($tt:tt)+) => {
26        $crate::proc_macro_api_parse_seg! {
27            [/*rest*/] [ { $($tt)+ } ] [/*prv*/]
28            [
29                [/*[proc]*/] [/*[doc]*/] [/*[[other]+[proc]]*/]
30                [ [/*cc*/] [/*al*/] ]
31            ]
32        }
33    };
34    () => {};
35}
36
37#[doc(hidden)]
38#[macro_export]
39macro_rules! proc_macro_api_err_attr_mul {
40    // [first] [second]
41    ($msg:expr , [ $($note:expr),* $(,)? ] , $plural_s:expr =>
42        [ $first_0:tt $($first:tt)* ] [ $second_0:tt $($second:tt)* ]
43        $path:tt
44    ) => {
45        $crate::__private::compile_error!($crate::__private::concat!(
46            $msg,
47            "\n/ #", $crate::__private::stringify!($first_0),
48            $("\n| #", $crate::__private::stringify!($first),)*
49            "\n|_^ the first attribute", $plural_s,
50            "\n...",
51            "\n/ #", $crate::__private::stringify!($second_0),
52            $("\n| #", $crate::__private::stringify!($second),)*
53            "\n|_^ the second attribute", $plural_s,
54            "\n\n  ", $crate::proc_macro_api_fmt_path!($path),
55            "\n  ^\n",
56            $("\n= note: ", $note,)*
57        ));
58    };
59}
60
61#[cfg(not(feature = "deny_shadow"))]
62#[doc(hidden)]
63#[macro_export]
64macro_rules! proc_macro_api_err_attr_shadow {
65    ($($tt:tt)*) => {};
66}
67
68#[cfg(feature = "deny_shadow")]
69#[doc(hidden)]
70#[macro_export]
71macro_rules! proc_macro_api_err_attr_shadow {
72    ([] $_0:tt $_1:tt) => {};
73
74    // [[proc]] [cover] [path]
75    ($proc:tt $cover:tt $path:tt) => {
76        $crate::proc_macro_api_err_attr_mul! {
77            "multiple proc-macro attributes are applied together",
78            [
79                "feature `deny_shadow` is enabled",
80                "disabling the feature can \
81leave the possible error to the compiler",
82            ],
83            "" =>
84            $proc [ $cover ] $path
85        }
86    };
87}
88
89#[cfg(not(feature = "deny_override"))]
90#[doc(hidden)]
91#[macro_export]
92macro_rules! proc_macro_api_err_attr_override {
93    ($($tt:tt)*) => {};
94}
95
96#[cfg(feature = "deny_override")]
97#[doc(hidden)]
98#[macro_export]
99macro_rules! proc_macro_api_err_attr_override {
100    ($_0:tt $($_1:tt)?) => {};
101
102    // [[old]] [[new]] [path]
103    ($old:tt $new:tt $path:tt) => {
104        $crate::proc_macro_api_err_attr_mul! {
105            "cannot override attributes",
106            [ "feature `deny_override` is enabled" ],
107            "s" =>
108            $old $new $path
109        }
110    };
111}
112
113#[cfg(not(feature = "deny_append"))]
114#[doc(hidden)]
115#[macro_export]
116macro_rules! proc_macro_api_err_attr_append {
117    ($($tt:tt)*) => {};
118}
119
120#[cfg(feature = "deny_append")]
121#[doc(hidden)]
122#[macro_export]
123macro_rules! proc_macro_api_err_attr_append {
124    ([] $_0:tt $_1:tt) => {};
125    ($_0:tt [] $_1:tt) => {};
126
127    // [[doc]] [[bg_doc]] [path]
128    ($doc:tt $bg_doc:tt $path:tt) => {
129        $crate::proc_macro_api_err_attr_mul! {
130            "cannot append attributes",
131            [ "feature `deny_append` is enabled" ],
132            "s" =>
133            $bg_doc $doc $path
134        }
135    };
136}
137
138#[doc(hidden)]
139#[macro_export]
140macro_rules! proc_macro_api_parse_attr {
141    // [doc]
142    (
143    [ [ doc $($arg_doc:tt)* ] $(, $at:tt)* ]
144    [ $($doc:tt)* ] $other:tt $proc:tt
145    [ $($seg:tt $($rest:tt)*)? ]
146    [ $($prv:tt)* ] [ $last:tt $($to_prv:tt)? ]
147    $bag:tt
148    ) => {
149        $crate::proc_macro_api_parse_attr! {
150            [ $($at),* ] [ $($doc)* [ doc $($arg_doc)* ] ] $other $proc
151            [ $($($rest)*)? ] [ $($prv)* $($to_prv)? ] [ $($seg)? $last ]
152            $bag
153        }
154    };
155
156    // -> out
157    (
158    [] [ $($doc:tt)* ] [ $($($other:tt)+)? ] [
159        $([ proc_macro $($arg_fn_0:tt)* ])?
160        $([ fn $($arg_fn:tt)* ])?
161        $([ proc_macro_attribute $($arg_at_0:tt)* ])?
162        $([ at $($arg_at:tt)* ])?
163        $([ proc_macro_derive $($arg_dr_0:tt)* ])?
164        $([ dr $($arg_dr:tt)* ])?
165    ]
166    [ $($seg:tt)* ]
167    [ $($prv:tt)* ] [ $last:tt $($to_prv:tt)? ]
168    [
169        [ $($bg_proc:tt)? ] [ $($bg_doc:tt)* ] [ $($bg_oth:tt)? ]
170        [ $($bg_prv:tt)* ] $path:tt
171    ]
172    ) => {
173        $crate::proc_macro_api_err_attr_append! {
174            [ $($doc)* ] [ $($bg_doc)* ]
175            [ $($prv)* $($to_prv)? $last $($seg)* ]
176        }
177        $crate::proc_macro_api_err_attr_override! {
178            $($bg_oth)? $([ $($other)+ ])?
179            [ $($prv)* $($to_prv)? $last $($seg)* ]
180        }
181        $crate::proc_macro_api_parse_seg! {
182            [ $($seg)* ] [ $last ] [ $($bg_prv)* $($prv)* $($to_prv)? ]
183            [
184                [
185                    $([ proc_macro $($arg_fn_0)* ] ;)?
186                    $([ proc_macro $($arg_fn)* ] ;)?
187                    $([ proc_macro_attribute $($arg_at_0)* ] ;)?
188                    $([ proc_macro_attribute $($arg_at)* ] ;)?
189                    $([ proc_macro_derive $($arg_dr_0)* ] ;)?
190                    $([ proc_macro_derive $($arg_dr)* ] ;)?
191                    $($bg_proc)?
192                ] [
193                    $($bg_doc)*
194                    $($doc)*
195                ] [
196                    $([ $($other)+ ] ;)?
197                    $($bg_oth)?
198                ] $path
199            ]
200        }
201    };
202
203    // [proc_macro]
204    // [proc_macro_attribute]
205    // [proc_macro_derive]
206    (
207    [
208        $([ proc_macro $($arg_fn_0:tt)* ])?
209        $([ fn $($arg_fn:tt)* ])?
210        $([ proc_macro_attribute $($arg_at_0:tt)* ])?
211        $([ at $($arg_at:tt)* ])?
212        $([ proc_macro_derive $($arg_dr_0:tt)* ])?
213        $([ dr $($arg_dr:tt)* ])?
214        $(, $at:tt)*
215    ]
216    $doc:tt [ $($other:tt)* ] [ $($proc:tt)? ]
217    [ $($seg:tt $($rest:tt)*)? ]
218    [ $($prv:tt)* ] [ $last:tt $($to_prv:tt)? ]
219    $bag:tt
220    ) => {
221        $crate::proc_macro_api_err_attr_shadow! {
222            [ $($proc)? ]
223            $([proc_macro$($arg_fn_0)*])?
224            $([fn$($arg_fn)*])?
225            $([proc_macro_attribute$($arg_at_0)*])?
226            $([at$($arg_at)*])?
227            $([proc_macro_derive$($arg_dr_0)*])?
228            $([dr$($arg_dr)*])?
229            [ $($prv)* $($to_prv)? $last $($seg $($rest)*)? ]
230        }
231        $crate::proc_macro_api_parse_attr! {
232            [ $($at),* ] $doc
233            [ $($other)*
234                $([ proc_macro $($arg_fn_0)* ])?
235                $([ proc_macro $($arg_fn)* ])?
236                $([ proc_macro_attribute $($arg_at_0)* ])?
237                $([ proc_macro_attribute $($arg_at)* ])?
238                $([ proc_macro_derive $($arg_dr_0)* ])?
239                $([ proc_macro_derive $($arg_dr)* ])?
240            ] [
241                $([proc_macro$($arg_fn_0)*])?
242                $([fn$($arg_fn)*])?
243                $([proc_macro_attribute$($arg_at_0)*])?
244                $([at$($arg_at)*])?
245                $([proc_macro_derive$($arg_dr_0)*])?
246                $([dr$($arg_dr)*])?
247            ]
248            [ $($($rest)*)? ] [ $($prv)* $($to_prv)? ] [ $($seg)? $last ]
249            $bag
250        }
251    };
252
253    // [`any`]
254    (
255    [ $any:tt $(, $at:tt)* ]
256    [ $($doc:tt)* ] $other:tt $proc:tt
257    [ $($seg:tt $($rest:tt)*)? ]
258    [ $($prv:tt)* ] [ $last:tt $($to_prv:tt)? ]
259    $bag:tt
260    ) => {
261        $crate::proc_macro_api_parse_attr! {
262            [ $($at),* ] [ $($doc)* $any ] $other $proc
263            [ $($($rest)*)? ] [ $($prv)* $($to_prv)? ] [ $($seg)? $last ]
264            $bag
265        }
266    };
267}
268
269#[doc(hidden)]
270#[macro_export]
271macro_rules! proc_macro_api_parse_seg {
272    (
273    [ $seg:tt $($rest:tt)* ] [ $last:tt ] [ $($prv:tt)* ] $bag:tt
274    ) => {
275        $crate::proc_macro_api_parse_seg! {
276            [ $($rest)* ] [ $seg ] [ $($prv)* $last ] $bag
277        }
278    };
279
280    (
281    [] [
282        $($api:ident)?
283        $({
284            $(# $at_0:tt)*
285            $($seg_0:ident)?
286            $(:: $seg_cc_0:ident $(:: $rest_0:ident)*)?
287            $(:: { $($seg_blk_cc_0:tt)* })?
288            $({ $($seg_blk_0:tt)* })?
289            $(as $al_0:tt)?
290            $(,
291                $(# $at:tt)*
292                $($seg:ident)?
293                $(:: $seg_cc:ident $(:: $rest:ident)*)?
294                $(:: { $($seg_blk_cc:tt)* })?
295                $({ $($seg_blk:tt)* })?
296                $(as $al:tt)?
297            )*
298        })?
299    ] $prv:tt
300    [ $bg_proc:tt $bg_doc:tt $bg_oth:tt [ $bg_cc:tt $bg_al:tt ] ]
301    ) => {
302        $(
303        $crate::proc_macro_api_parse_fn! {
304            $bg_al $bg_proc [ $bg_doc $bg_oth $bg_cc $prv ] $api
305        }
306        )?
307        $(
308        $crate::proc_macro_api_err_seg_blk_al! {
309            $bg_al
310        }
311        $crate::proc_macro_api_parse_seg_call_attr! {
312            [
313                $(0 $bg_cc [] $seg_0)?
314                $(1 [ :: ] [ :: ] $seg_cc_0 2 [ $($rest_0)* ])?
315                $(3 [ :: ] [ :: ] { $($seg_blk_cc_0)* })?
316                $(4 $bg_cc [] { $($seg_blk_0)* })?
317            ]
318            [ $($at_0),* ] [ $($al_0)? ]
319            [ $prv $bg_cc $bg_proc $bg_doc $bg_oth ]
320        }
321        $(
322        $crate::proc_macro_api_parse_seg_call_attr! {
323            [
324                $(0 $bg_cc [] $seg)?
325                $(1 [ :: ] [ :: ] $seg_cc 2 [ $($rest)* ])?
326                $(3 [ :: ] [ :: ] { $($seg_blk_cc)* })?
327                $(4 $bg_cc [] { $($seg_blk)* })?
328            ]
329            [ $($at),* ] [ $($al)? ]
330            [ $prv $bg_cc $bg_proc $bg_doc $bg_oth ]
331        }
332        )*
333        )?
334    };
335}
336
337#[doc(hidden)]
338#[macro_export]
339macro_rules! proc_macro_api_err_seg_blk_al {
340    ([]) => {};
341
342    ([ $al:tt ]) => {
343        $crate::__private::compile_error!($crate::__private::concat!(
344            "no rules expected `as`",
345            "\n  {...} as ",
346            $crate::__private::stringify!($al),
347            "\n        ^^",
348        ));
349    };
350}
351
352#[doc(hidden)]
353#[macro_export]
354macro_rules! proc_macro_api_parse_seg_call_attr {
355    (
356    [
357        $_i:tt $cc:tt $cc_tag:tt $seg:tt
358        $(1 [ :: ] [ :: ] $seg_cc:tt)?
359        $(2 [ $($rest:tt)* ])?
360        $(3 [ :: ] [ :: ] $seg_blk_cc:tt)?
361    ]
362    $at:tt $al:tt
363    [
364        $prv:tt $bg_cc:tt
365        [ $($bg_proc:tt)? $(; $_0:tt)? $(;)? ] $bg_doc:tt
366        [ $($bg_oth:tt)? $(; $_1:tt)? $(;)? ]
367    ]
368    ) => {
369        $crate::proc_macro_api_err_seg_inner_cc! {
370            $cc_tag $bg_cc $prv [ $seg ]
371        }
372        $crate::proc_macro_api_err_seg_gp_attr! {
373            $at [ $_i $($seg_blk_cc)? ] [
374                $cc_tag $_i $seg $(1 $seg_cc)? $(2 [ $($rest)* ])?
375            ]
376        }
377        $crate::proc_macro_api_parse_attr! {
378            $at [/*[doc]*/] [/*[other]+[proc]*/] [/*[proc]*/]
379            [ $($seg_cc)? $($($rest)*)? $($seg_blk_cc)? ] [/*prv*/] [ $seg ]
380            [
381                [ $($bg_proc)? ] $bg_doc [ $($bg_oth)? ]
382                $prv [ $cc $al ]
383            ]
384        }
385    };
386
387    ([] [] [] $_:tt) => { /* empty comma (`,,`) and trailing comma (`... ,`) */ };
388
389    // err: no seg
390    ([] $at:tt $al:tt $_:tt) => {
391        $crate::proc_macro_api_err_seg_no_seg! {
392            $at $al
393        }
394    };
395
396    // err: multiple seg
397    (
398    [
399        $(0 $cc_0:tt [] $seg:tt)?
400        $(1 [ :: ] [ :: ] $seg_cc:tt)?
401        $(2 [ $($rest:tt)* ])?
402        $(3 [ :: ] [ :: ] $seg_blk_cc:tt)?
403        4 $cc_1:tt [] $seg_blk:tt
404    ]
405    $at:tt $al:tt $_:tt
406    ) => {
407        $crate::proc_macro_api_err_syn_gt_one! {
408            "" =>
409            [
410                $($seg)? $(:: $seg_cc)? $($(:: $rest)*)?
411                $(:: $seg_blk_cc)?
412            ]
413            [ $seg_blk ]
414        }
415    };
416}
417
418#[doc(hidden)]
419#[macro_export]
420macro_rules! proc_macro_api_err_seg_inner_cc {
421    ([] $_0:tt $_1:tt $_:tt) => {};
422    ([ :: ] [] [] $_:tt) => {};
423
424    // [path]
425    ([ :: ] $_0:tt $_1:tt $path:tt) => {
426        $crate::__private::compile_error!($crate::__private::concat!(
427            "leading `::` is in the middle of a path",
428            "\n  :: ",
429            $crate::proc_macro_api_fmt_path!($path),
430            "\n  ^^",
431        ));
432    };
433}
434
435#[doc(hidden)]
436#[macro_export]
437macro_rules! proc_macro_api_err_seg_no_seg {
438    // [at] al
439    ([ $($at_0:tt $(, $at:tt)*)? ] [ $($al:tt)? ]) => {
440        $crate::__private::compile_error!($crate::__private::concat!(
441            "expected path segments or a path group",
442            "\n/",
443            $(
444            "\n| #", $crate::__private::stringify!($at_0),
445            $("\n| #", $crate::__private::stringify!($at),)*
446            )?
447            $("\n| as ", $crate::__private::stringify!($al),)?
448            "\n|\n|_^ expected path segments or a path group",
449        ));
450    };
451}
452
453#[cfg(not(feature = "deny_group_attr"))]
454#[doc(hidden)]
455#[macro_export]
456macro_rules! proc_macro_api_err_seg_gp_attr {
457    ($($tt:tt)*) => {};
458}
459
460#[cfg(feature = "deny_group_attr")]
461#[doc(hidden)]
462#[macro_export]
463macro_rules! proc_macro_api_err_seg_gp_attr {
464    ([] $_:tt $path:tt) => {};
465    ($at:tt [ $(0)? $(1)? ] $path:tt) => {};
466
467    (
468        [ $at_0:tt $(, $at:tt)* ] $_:tt
469        [
470            [ $($cc:tt)? ]
471            $(0 $seg:tt)?
472            $(1 $seg_cc:tt)?
473            $(2 [ $($rest:tt)* ])?
474            $(3 $seg_blk_cc:tt)?
475            $(4 $seg_blk:tt)?
476        ]
477    ) => {
478        $crate::__private::compile_error!($crate::__private::concat!(
479            "attributes are applied to a path group",
480            "\n/ #", $crate::__private::stringify!($at_0),
481            $("\n| #", $crate::__private::stringify!($at),)*
482            "\n| ",
483            $crate::proc_macro_api_fmt_str_tt! {
484                $($cc)? $($seg ::)? $($seg_cc ::)? $($($rest ::)*)? { ... }
485            },
486            "\n|_^",
487            "\n= note: feature `deny_group_attr` is enabled",
488        ));
489    };
490}
491
492#[doc(hidden)]
493#[macro_export]
494macro_rules! proc_macro_api_err_fn_no_proc {
495    ([ $($cc:tt)? ] [ $($prv:tt)* ] [ $($al:tt)? ] $api:tt) => {
496        $crate::__private::compile_error!($crate::__private::concat!(
497            "expected a proc-macro attribute",
498            "\n/ ", $($crate::__private::stringify!($cc),)?
499            $($crate::__private::stringify!($prv), "::",)*
500            $crate::__private::stringify!($api),
501            $("\n| as ", $crate::__private::stringify!($al),)?
502            "\n|_^",
503        ));
504    };
505}
506
507#[doc(hidden)]
508#[macro_export]
509macro_rules! proc_macro_api_parse_fn {
510    ([ _ ] $proc:tt $bag:tt $api:tt) => { /* underscore alias */ };
511
512    ($al:tt [] [ $_0:tt $_1:tt $cc:tt $prv:tt ] $api:tt) => {
513        $crate::proc_macro_api_err_fn_no_proc!($cc $prv $al $api);
514    };
515
516    // $bg_al $bg_proc [ $bg_doc $bg_oth $bg_cc $prv ] $api
517    (
518    [ $($al:tt)? ]
519    [
520        $([ proc_macro $($arg_fn:tt)* ])?
521        $([ proc_macro_attribute $($arg_at:tt)* ])?
522        $([ proc_macro_derive $($arg_dr:tt)* ])?
523        $(; $_0:tt)? $(;)?
524    ]
525    [ $doc:tt [ $other:tt $(; $_1:tt)? $(;)? ] $cc:tt $prv:tt ]
526    $api:tt
527    ) => {
528        $crate::proc_macro_api_fn! {
529            $doc $other $cc $prv $api [ $($al)? $api ]
530            $((input) [ $($arg_fn)* ])?
531            $((args, item) [ $($arg_at)* ])?
532            $((item) [ $($arg_dr)* ])?
533        }
534    };
535}
536
537#[doc(hidden)]
538#[macro_export]
539macro_rules! proc_macro_api_fn {
540    (
541    [ $($doc:tt)* ] [ $($other:tt)* ]
542    [ $($cc:tt)? ] [ $($prv:tt)* ] $api:tt [ $name:tt $($_0:tt)? ]
543    ( $($args:tt),* $(,)? ) $_1:tt
544    ) => {
545        $(# $doc)*
546        $(# $other)*
547        pub fn $name (
548            $($args : $crate::__private::TokenStream),*
549        ) -> $crate::__private::TokenStream {
550            $crate::proc_macro_api_call! {
551                ( $($args),* ) $($cc)? $($prv ::)* $api
552            }
553        }
554    };
555}
556
557#[cfg(not(feature = "auto_transform"))]
558#[doc(hidden)]
559#[macro_export]
560macro_rules! proc_macro_api_call {
561    ($args:tt $($path:tt)*) => {
562        $($path)* $args
563    };
564}
565
566#[cfg(feature = "auto_transform")]
567#[doc(hidden)]
568#[macro_export]
569macro_rules! proc_macro_api_call {
570    (( $($args:tt),* ) $($path:tt)*) => {
571        $crate::__private::From::from(
572            $($path)* (
573                $($crate::__private::From::from($args),)*
574            ),
575        )
576    };
577}