replace_self_ty/
lib.rs

1//! Macro magic to replace all instances of `Self` in a token tree.
2//!
3//! Mostly for illustration / learning purposes, check out [the source] for
4//! details on how it works.
5//!
6//! See also:
7//! - [The Little Book of Rust Macros](https://lukaswirth.dev/tlborm/).
8//! - [Anything you can do, I can do worse with macro_rules!](https://www.youtube.com/watch?v=7uSM60jlkBE).
9//! - [Aurorans Solis' Blog](https://auroranssolis.github.io/).
10//!
11//! [the source]: https://github.com/madsmtm/replace_self_ty
12#![no_std]
13
14/// Replace instances of `Self` with another type inside a syntax tree.
15///
16/// This isn't that useful by itself, but it might be useful inside larger
17/// macros that wants to use the result in a context outside of an `impl`.
18///
19/// # Examples
20///
21/// ```
22/// use replace_self_ty::replace_self_ty;
23///
24/// struct Foo;
25///
26/// replace_self_ty! {
27///     (Foo)
28///
29///     impl Foo {
30///         fn foo(self: &Self) -> Self {
31///             Self
32///         }
33///     }
34/// }
35///
36/// // Becomes:
37/// // impl Foo {
38/// //     fn foo(self: &Foo) -> Foo {
39/// //         Foo
40/// //     }
41/// // }
42/// ```
43///
44/// # Limitations
45///
46/// This works at the syntax level, so it cannot handle cases like:
47///
48/// ```
49/// use replace_self_ty::replace_self_ty;
50///
51/// struct Foo;
52///
53/// macro_rules! get_self {
54///     () => {
55///         Self
56///     };
57/// }
58///
59/// replace_self_ty! {
60///     (Foo)
61///
62///     impl Foo {
63///         fn foo() -> get_self!() {
64///             get_self!()
65///         }
66///     }
67/// }
68///
69/// // `get_self!()` isn't replaced by `Foo`.
70/// ```
71///
72/// For large syntax trees, it also requires a fairly large recursion limit,
73/// so this is probably unsuitable for that (at least with the current
74/// implementation).
75#[macro_export]
76macro_rules! replace_self_ty {
77    (
78        // The type that we want to replace `Self` with.
79        ($($new_self_ty:tt)*)
80
81        // The syntax tree that we want to replace `Self` in.
82        $($t:tt)*
83    ) => {
84        $crate::__replace_self_ty_inner! {
85            ($($new_self_ty)*)
86            ($($t)*)
87            ()
88
89            ($crate::__replace_self_ty_out)
90        }
91    };
92}
93
94#[doc(hidden)]
95#[macro_export]
96macro_rules! __replace_self_ty_inner {
97    // Nothing more to parse; we're done.
98    (
99        ($($new_self_ty:tt)*)
100        ()
101        ($($parsed:tt)*)
102
103        ($($out_macro:tt)*)
104        $($out_args:tt)*
105    ) => {
106        // compile_error!(stringify!($($parsed)*));
107        $($out_macro)* ! {
108            $($out_args)*
109
110            ($($parsed)*)
111        }
112    };
113
114    // Found Self type; replace it and continue.
115    (
116        ($($new_self_ty:tt)*)
117        (Self $($rest:tt)*)
118        ($($parsed:tt)*)
119
120        ($($out_macro:tt)*)
121        $($out_args:tt)*
122    ) => {
123        $crate::__replace_self_ty_inner! {
124            ($($new_self_ty)*)
125            ($($rest)*)
126            ($($parsed)* $($new_self_ty)*)
127
128            ($($out_macro)*)
129            $($out_args)*
130        }
131    };
132
133    // Recurse into different kinds of token groups.
134
135    // Parentheses.
136    (
137        ($($new_self_ty:tt)*)
138        (($($inner:tt)*) $($rest:tt)*)
139        ($($parsed:tt)*)
140
141        ($($out_macro:tt)*)
142        $($out_args:tt)*
143    ) => {
144        $crate::__replace_self_ty_inner! {
145            ($($new_self_ty)*)
146            ($($inner)*)
147            ()
148
149            ($crate::__replace_self_ty_in_parentheses)
150            ($($new_self_ty)*)
151            ($($rest)*)
152            ($($parsed)*)
153
154            ($($out_macro)*)
155            ($($out_args)*)
156        }
157    };
158
159    // Square brackets.
160    (
161        ($($new_self_ty:tt)*)
162        ([$($inner:tt)*] $($rest:tt)*)
163        ($($parsed:tt)*)
164
165        ($($out_macro:tt)*)
166        $($out_args:tt)*
167    ) => {
168        $crate::__replace_self_ty_inner! {
169            ($($new_self_ty)*)
170            ($($inner)*)
171            ()
172
173            ($crate::__replace_self_ty_in_square_brackets)
174            ($($new_self_ty)*)
175            ($($rest)*)
176            ($($parsed)*)
177
178            ($($out_macro)*)
179            ($($out_args)*)
180        }
181    };
182
183    // Curly brackets.
184    (
185        ($($new_self_ty:tt)*)
186        ({$($inner:tt)*} $($rest:tt)*)
187        ($($parsed:tt)*)
188
189        ($($out_macro:tt)*)
190        $($out_args:tt)*
191    ) => {
192        $crate::__replace_self_ty_inner! {
193            ($($new_self_ty)*)
194            ($($inner)*)
195            ()
196
197            ($crate::__replace_self_ty_in_curly_brackets)
198            ($($new_self_ty)*)
199            ($($rest)*)
200            ($($parsed)*)
201
202            ($($out_macro)*)
203            ($($out_args)*)
204        }
205    };
206
207    // Any other token tree is simply passed onwards.
208    (
209        ($($new_self_ty:tt)*)
210        ($token:tt $($rest:tt)*)
211        ($($parsed:tt)*)
212
213        ($($out_macro:tt)*)
214        $($out_args:tt)*
215    ) => {
216        $crate::__replace_self_ty_inner! {
217            ($($new_self_ty)*)
218            ($($rest)*)
219            ($($parsed)* $token)
220
221            ($($out_macro)*)
222            $($out_args)*
223        }
224    };
225}
226
227#[doc(hidden)]
228#[macro_export]
229macro_rules! __replace_self_ty_in_parentheses {
230    (
231        ($($new_self_ty:tt)*)
232        ($($rest:tt)*)
233        ($($parsed:tt)*)
234
235        ($($out_macro:tt)*)
236        ($($out_args:tt)*)
237
238        ($($parsed_group:tt)*)
239    ) => {
240        $crate::__replace_self_ty_inner! {
241            ($($new_self_ty)*)
242            ($($rest)*)
243            ($($parsed)* ($($parsed_group)*))
244
245            ($($out_macro)*)
246            $($out_args)*
247        }
248    };
249}
250
251#[doc(hidden)]
252#[macro_export]
253macro_rules! __replace_self_ty_in_square_brackets {
254    (
255        ($($new_self_ty:tt)*)
256        ($($rest:tt)*)
257        ($($parsed:tt)*)
258
259        ($($out_macro:tt)*)
260        ($($out_args:tt)*)
261
262        ($($parsed_group:tt)*)
263    ) => {
264        $crate::__replace_self_ty_inner! {
265            ($($new_self_ty)*)
266            ($($rest)*)
267            ($($parsed)* [$($parsed_group)*])
268
269            ($($out_macro)*)
270            $($out_args)*
271        }
272    };
273}
274
275#[doc(hidden)]
276#[macro_export]
277macro_rules! __replace_self_ty_in_curly_brackets {
278    (
279        ($($new_self_ty:tt)*)
280        ($($rest:tt)*)
281        ($($parsed:tt)*)
282
283        ($($out_macro:tt)*)
284        ($($out_args:tt)*)
285
286        ($($parsed_group:tt)*)
287    ) => {
288        $crate::__replace_self_ty_inner! {
289            ($($new_self_ty)*)
290            ($($rest)*)
291            ($($parsed)* {$($parsed_group)*})
292
293            ($($out_macro)*)
294            $($out_args)*
295        }
296    };
297}
298
299#[doc(hidden)]
300#[macro_export]
301macro_rules! __replace_self_ty_out {
302    (
303        ($($parsed:tt)*)
304    ) => {
305        $($parsed)*
306    };
307}