blob: 9ec6df09a1b39dba05f2b256db04d4bed688447d [file] [log] [blame]
Jason Macnakbbac34b2020-03-25 01:28:44 +00001//! Support for nested invocations of proc-macro-hack expression macros.
2//!
3//! By default, macros defined through proc-macro-hack do not support nested
4//! invocations, i.e. the code emitted by a proc-macro-hack macro invocation
5//! cannot contain recursive calls to the same proc-macro-hack macro nor calls
6//! to any other proc-macro-hack macros.
7//!
8//! This crate provides opt-in support for such nested invocations.
9//!
10//! To make a macro callable recursively, add a dependency on this crate from
11//! your declaration crate and update the `#[proc_macro_hack]` re-export as
12//! follows.
13//!
14//! ```
15//! // Before
16//! # const IGNORE: &str = stringify! {
17//! #[proc_macro_hack]
18//! pub use demo_hack_impl::add_one;
19//! # };
20//! ```
21//!
22//! ```
23//! // After
24//! # const IGNORE: &str = stringify! {
25//! #[proc_macro_hack(support_nested)]
26//! pub use demo_hack_impl::add_one;
27//! # };
28//! ```
29//!
30//! No change is required within your definition crate, only to the re-export in
31//! the declaration crate.
32//!
33//! # Limitations
34//!
35//! - Nested invocations are preprocessed by a TT-muncher, so the caller's crate
36//! will be required to contain `#![recursion_limit = "..."]` if there are
37//! lengthy macro invocations.
38//!
39//! - Only up to 64 nested invocations are supported.
40
41#![no_std]
42
Matthew Maurerfe7c85d2020-07-06 13:22:35 -070043// ANDROID: Use std to allow building as a dylib.
44extern crate std;
45
Chih-Hung Hsieh905c18a2020-10-25 03:57:56 -070046include!(concat!(env!("OUT_DIR"), "/count.rs"));
Jason Macnakbbac34b2020-03-25 01:28:44 +000047
48#[doc(hidden)]
49#[macro_export]
50macro_rules! dispatch {
51 (() $($bang:tt)*) => {
52 $crate::count!($($bang)*)
53 };
54 ((($($first:tt)*) $($rest:tt)*) $($bang:tt)*) => {
55 $crate::dispatch!(($($first)* $($rest)*) $($bang)*)
56 };
57 (([$($first:tt)*] $($rest:tt)*) $($bang:tt)*) => {
58 $crate::dispatch!(($($first)* $($rest)*) $($bang)*)
59 };
60 (({$($first:tt)*} $($rest:tt)*) $($bang:tt)*) => {
61 $crate::dispatch!(($($first)* $($rest)*) $($bang)*)
62 };
63 ((! $($rest:tt)*) $($bang:tt)*) => {
64 $crate::dispatch!(($($rest)*) $($bang)* !)
65 };
66 ((!= $($rest:tt)*) $($bang:tt)*) => {
67 $crate::dispatch!(($($rest)*) $($bang)* !)
68 };
69 (($first:tt $($rest:tt)*) $($bang:tt)*) => {
70 $crate::dispatch!(($($rest)*) $($bang)*)
71 };
72}