macro_rules_attribute/lib.rs
1/*!
2[apply]: apply
3[derive]: derive
4[`derive_alias!`]: derive_alias
5[`macro_rules_attribute`]: macro_rules_attribute
6[`macro_rules_derive`]: macro_rules_derive
7*/
8#![cfg_attr(feature = "better-docs",
9 cfg_attr(all(), doc = include_str!("../README.md"))
10)]
11#![cfg_attr(feature = "better-docs",
12 feature(doc_auto_cfg),
13)]
14#![no_std]
15#![forbid(unsafe_code)]
16
17/// Legacy name for what is currently named <code>#\[[apply]]</code>
18///
19/// Despite being a slightly clearer name (than `#[apply]` is) w.r.t. what it
20/// does, `#[macro_rules_attribute]` had the big drawback of being a mouthful.
21///
22/// Hence the `#[apply]` alias being born, and now even superseding
23/// `#[macro_rules_attribute]` altogether as the author-deemed "idiomatic"
24/// name to favor.
25pub use ::macro_rules_attribute_proc_macro::macro_rules_attribute;
26
27/// Applies the given `macro_rules!` macro to the decorated item.
28///
29/// This, as with any `proc_macro_attribute`, **consumes** the item it
30/// decorates: it is the `macro_rules!` macro job to generate it (_it is thus
31/// able to modify it_!).
32///
33/// For a version with "read-only" access to the item it decorates, see
34/// [`macro_rules_derive`][`macro@macro_rules_derive`].
35///
36/// ## Examples
37///
38/// ### Deriving getters for a (non-generic) `struct`
39///
40/// Imagine having define the following handy `make_getters!` (`macro_rules!`)
41/// macro:
42///
43/** ```rust
44macro_rules! make_getters {(
45 $(#[$struct_meta:meta])*
46 $struct_vis:vis
47 struct $StructName:ident {
48 $(
49 $(#[$field_meta:meta])*
50 $field_vis:vis // this visibility will be applied to the getters instead
51 $field_name:ident : $field_ty:ty
52 ),* $(,)?
53 }
54) => (
55 // First, generate the struct definition we have been given, but with
56 // private fields instead.
57 $(#[$struct_meta])*
58 $struct_vis
59 struct $StructName {
60 $(
61 $(#[$field_meta])*
62 // notice the lack of visibility => private fields
63 $field_name: $field_ty,
64 )*
65 }
66
67 // Then, implement the getters:
68 impl $StructName {
69 $(
70 #[inline]
71 $field_vis
72 fn $field_name (self: &'_ Self)
73 -> &'_ $field_ty
74 {
75 &self.$field_name
76 }
77 )*
78 }
79)}
80``` */
81///
82/// Basically allowing you to write:
83///
84/** ```rust ,compile_fail
85use example::Person;
86mod example {
87 make_getters! {
88 /// The macro handles meta attributes such as docstrings
89 pub
90 struct Person {
91 pub
92 name: String,
93
94 pub
95 age: u8,
96 }
97 }
98}
99
100fn is_new_born (person: &'_ mut Person)
101 -> bool
102{
103 // Reading the value through the getter is fine…
104 return *person.age() == 0;
105 // But trying to mutate it by skipping the getter is not 💪
106 person.age = 0;
107 // ^ error[E0616]: field `age` of struct `example::Person` is private
108}
109``` */
110///
111/// This is fine, _etc._, but that rightward drift on `make_getters! {` syntax
112/// problematic:
113///
114/// - Incurs in extra rightward drift and thus, noise.
115///
116/// - Worse, **it leads to a non-escalable / composable pattern**: if we had a
117/// second macro, say `make_setters!`, our syntax is unable to handle both
118/// macros being called on the same type definition.
119///
120/// Hence `::macro_rules_attribute`'s <code>#\[[apply]\]</code> (formerly called
121/// `#[macro_rules_attribute]` itself) helper:
122///
123/** ```rust
124# fn main () {}
125#[macro_use]
126extern crate macro_rules_attribute;
127
128use example::Person;
129mod example {
130 #[apply(make_getters!)] // or `#[apply(make_getters)]`: the final `!` is not mandatory
131 /// The macro handles meta attributes such as docstrings
132 pub
133 struct Person {
134 pub
135 name: String,
136
137 pub
138 age: u8,
139 }
140 # // where;
141 # macro_rules! make_getters {(
142 # $(#[$struct_meta:meta])*
143 # $struct_vis:vis
144 # struct $StructName:ident {
145 # $(
146 # $(#[$field_meta:meta])*
147 # $field_vis:vis // this visibility will be applied to the getters instead
148 # $field_name:ident : $field_ty:ty
149 # ),* $(,)?
150 # }
151 # ) => (
152 # // First, generate the struct definition we have been given, but with
153 # // private fields instead.
154 # $(#[$struct_meta])*
155 # $struct_vis
156 # struct $StructName {
157 # $(
158 # $(#[$field_meta])*
159 # // notice the lack of visibility => private fields
160 # $field_name: $field_ty,
161 # )*
162 # }
163
164 # // Then, implement the getters:
165 # impl $StructName {
166 # $(
167 # #[inline]
168 # $field_vis
169 # fn $field_name (self: &'_ Self)
170 # -> &'_ $field_ty
171 # {
172 # &self.$field_name
173 # }
174 # )*
175 # }
176 # )} use make_getters;
177}
178
179fn is_new_born (person: &'_ Person)
180 -> bool
181{
182 // Reading the value through the getter is fine…
183 *person.age() == 0
184 // But trying to mutate it by skipping the getter is not 💪
185 // person.age == 0
186 // ^ error[E0616]: field `age` of struct `example::Person` is private
187}
188``` */
189pub use ::macro_rules_attribute_proc_macro::macro_rules_attribute as apply;
190
191/// Applies the given `macro_rules!` macro to the decorated item.
192///
193/// This, as with any `#[derive(...)]`, **does not consume** the item it
194/// decorates: instead, it only generates code on top of it.
195///
196/// ## Examples
197///
198/// ### Implementing `Into<Int>` for a given `#[repr(Int)]` `enum`:
199///
200/** ```rust
201#[macro_use]
202extern crate macro_rules_attribute;
203
204macro_rules! ToInteger {(
205 #[repr($Int:ident)]
206 $(#[$enum_meta:meta])*
207 $pub:vis
208 enum $Enum:ident {
209 $(
210 $Variant:ident $(= $value:expr)?
211 ),* $(,)?
212 }
213) => (
214 impl ::core::convert::From<$Enum> for $Int {
215 #[inline]
216 fn from (x: $Enum)
217 -> Self
218 {
219 x as _
220 }
221 }
222)}
223
224#[macro_rules_derive(ToInteger)] // or `#[macro_rules_derive(ToInteger!)]`
225#[repr(u32)]
226enum Bool {
227 False,
228 True,
229}
230
231fn main ()
232{
233 assert_eq!(u32::from(Bool::False), 0);
234 assert_eq!(u32::from(Bool::True), 1);
235 // assert_eq!(u8::from(Bool::False), 0);
236 // ^ error[E0277]: the trait bound `u8: std::convert::From<main::Bool>` is not satisfied
237}
238``` */
239///
240/// ## Difference with <code>#\[[derive]\]</code>
241///
242/// <code>#\[[macro_rules_derive]\]</code> is specifically intended to be used
243/// with `macro_rules!`-based derives:
244///
245/// - it won't accept classic derives;
246///
247/// - thanks to that, the trailing `!` on the macro name is not mandatory.
248///
249/// For <code>#\[[derive]\]</code>, it's exactly the opposite.
250pub use ::macro_rules_attribute_proc_macro::macro_rules_derive;
251
252/// Convenience macro to define new derive aliases.
253///
254/// The so-defined macros are intended to be used by
255/// <code>#\[[macro_rules_derive]]</code> or this crate's
256/// <code>#\[[derive]]</code>.
257///
258/// ## Examples
259///
260/** ```rust
261# fn main () {}
262#[macro_use]
263extern crate macro_rules_attribute;
264
265derive_alias! {
266 #[derive(Copy!)] = #[derive(Clone, Copy)];
267 #[derive(Eq!)] = #[derive(PartialEq, Eq)];
268 #[derive(Ord!)] = #[derive(Eq!, PartialOrd, Ord)];
269}
270
271#[derive(Debug, Copy!, Ord!)]
272struct Foo {
273 // …
274}
275
276// Note: this defines `Copy!`, `Eq!` and `Ord!` as properly scoped
277// `crate`-local macros.
278mod example {
279 use super::Copy;
280
281 #[derive(Copy!, super::Eq!)]
282 struct Bar;
283}
284``` */
285///
286/** ```rust
287# fn main () {}
288#[macro_use]
289extern crate macro_rules_attribute;
290
291use ::core::{fmt::Debug, hash::Hash};
292
293/// Trait alias pattern: `T : TheUsualSuspects ⇔ T : Debug + Copy + Ord + Hash`.
294trait TheUsualSuspects
295where // `⇒` direction
296 Self : Debug + Copy + Ord + Hash,
297{}
298impl<T : ?Sized> TheUsualSuspects for T
299where // `⇐` direction
300 Self : Debug + Copy + Ord + Hash,
301{}
302
303derive_alias! {
304 #[derive(TheUsualSuspects!)] = #[derive(
305 Debug,
306 Copy, Clone,
307 Ord, PartialOrd, Eq, PartialEq,
308 Hash,
309 )];
310}
311
312#[derive(TheUsualSuspects!)]
313struct KeyserSöze;
314
315const _: () = {
316 fn compile_time_assert_impls<T : ?Sized> ()
317 where
318 T : TheUsualSuspects,
319 {}
320
321 let _ = compile_time_assert_impls::<KeyserSöze>;
322};
323``` */
324///
325/// ### Caveat regarding derive helpers (inert-made attributes)
326///
327/// <details><summary>Click to see</summary>
328///
329/// Some derive attributes (such as `{De,}Serialize`), can involve helper
330/// attributes (such as `#[serde]`).
331/// This yields
332/// <a href="https://doc.rust-lang.org/1.60.0/reference/attributes.html#active-and-inert-attributes" target="_blank">inert</a>
333/// derive-<a href="https://doc.rust-lang.org/1.60.0/reference/procedural-macros.html#derive-macro-helper-attributes" target="_blank">helper-attributes</a>,
334/// which represent a _semantic_ aspect of the derive that
335/// **non-compiler-blessed macros such as this one cannot possibly know about**.
336///
337/// This makes aliasing such derives problematic, **since the `derive` aliases
338/// won't be able to handle the helper attributes**.
339///
340/** ```rust ,compile_fail
341# fn main () {}
342#[macro_use]
343extern crate macro_rules_attribute;
344
345derive_alias! {
346 #[derive(Serde!)] = #[derive(::serde::Deserialize, ::serde::Serialize)];
347}
348
349#[derive(Serde!)]
350#[serde(rename_all = "snake_case")] // Error, unknown `#[serde]` attribute
351struct Mejrs {
352 swaginess: u8,
353}
354``` */
355///
356/// The above, for instance, yields something along the lines of:
357///
358/** ```rust
359# #[cfg(any())] macro_rules! ignore {
360 error: cannot find attribute "serde" in this scope
361 --> src/lib.rs:11:3
362 |
363 11 | #[serde(rename_all = "snake_case")]
364 | ^^^^^
365 |
366 = note: "serde" is in scope, but it is a crate, not an attribute
367# }
368``` */
369///
370/// The only solution is to forgo the niceties of a `derive_alias!`, and define
371/// your own <code>#\[[apply]\]</code>-able `macro_rules_attribute` that aliases
372/// the `#[derive(…)]` attribute as a whole. [`attribute_alias!`] can come in
373/// handy in such situations:
374///
375/** ```rust
376# fn main () {}
377#[macro_use]
378extern crate macro_rules_attribute;
379
380attribute_alias! {
381 #[apply(derive_Serde)] = #[derive(::serde::Deserialize, ::serde::Serialize)];
382}
383
384#[apply(derive_Serde)]
385#[serde(rename_all = "snake_case")] // OK
386struct Mejrs {
387 swaginess: u8,
388}
389``` */
390///
391/// ___
392///
393/// </details>
394#[macro_export]
395macro_rules! derive_alias {(
396 $(
397 #[derive($MacroName:ident !)] = #[derive($($derives:tt)*)];
398 )*
399) => (
400 $crate::ඞ_with_dollar! {( $_:tt ) => (
401 $crate::ඞ::paste! {
402 $(
403 // To avoid ambiguities with what the re-export
404 // refers to, let's use a hopefully unused name.
405 //
406 // Indeed, eponymous derive macros in scope such as those
407 // from the prelude would otherwise cause trouble with the
408 // re-export line.
409 #[allow(nonstandard_style)]
410 macro_rules! [< $MacroName __derive_macro >] {(
411 $_($item:tt)*
412 ) => (
413 $crate::ඞ_nested_derive! {
414 #[derive($($derives)*)]
415 $_($item)*
416 }
417 )}
418 #[allow(unused_imports)]
419 pub(in crate) use [< $MacroName __derive_macro >] as $MacroName;
420 )*
421 }
422 )}
423)}
424
425
426/// Convenience macro to define new attribute aliases.
427///
428/// The so-defined macros are intended to be used by <code>#\[[apply]]</code>.
429///
430/// ## Examples
431///
432/** ```rust
433# fn main () {}
434#[macro_use]
435extern crate macro_rules_attribute;
436
437attribute_alias! {
438 #[apply(complex_cfg)] = #[cfg(
439 any(
440 test,
441 doc,
442 all(
443 feature = "some very complex cfg",
444 target_arch = "…",
445 ),
446 )
447 )];
448
449 #[apply(NOT_PART_OF_THE_PUBLIC_API!)] =
450 /// Not part of the public API
451 #[doc(hidden)]
452 ;
453}
454
455#[apply(complex_cfg)]
456struct Foo {
457 // …
458}
459
460#[apply(NOT_PART_OF_THE_PUBLIC_API!)]
461pub mod __macro_internals {
462 // …
463}
464``` */
465///
466#[macro_export]
467macro_rules! attribute_alias {(
468 $(
469 #[apply($name:ident $(!)?)] = $( #[$($attrs:tt)*] )+;
470 )*
471) => (
472 $(
473 $crate::ඞ_with_dollar! {( $_:tt ) => (
474 // Let's not do the paste + module + re-export dance here since it
475 // is less likely for an attribute name to collide with a prelude item.
476 #[allow(nonstandard_style)]
477 macro_rules! $name {( $_($item:tt)* ) => (
478 $( #[$($attrs)*] )+
479 $_($item)*
480 )}
481 #[allow(unused_imports)]
482 pub(in crate) use $name;
483 )}
484 )*
485)}
486
487#[doc(hidden)] /** Not part of the public API*/ #[macro_export]
488macro_rules! ඞ_with_dollar {( $($rules:tt)* ) => (
489 macro_rules! __emit__ { $($rules)* }
490 __emit__! { $ }
491)}
492
493/// Like <code>#\[[macro_rules_derive]\]</code>, but for allowing to be
494/// used to shadow [the "built-in" `#[derive]` attribute][1] (on Rust ≥ 1.57.0).
495///
496/// [1]: https://doc.rust-lang.org/stable/core/prelude/v1/macro.derive.html
497///
498/// That is, it is made a bit more lenient to allow for things such as:
499/** ```rust
500#[macro_use]
501extern crate macro_rules_attribute;
502
503derive_alias! {
504 #[derive(Eq!)] = #[derive(PartialEq, Eq)];
505}
506
507#[derive(Debug, Eq!)]
508struct Foo;
509
510fn main ()
511{
512 assert_eq!(Foo, Foo);
513}
514``` */
515///
516/// This is achieved thanks to **checking for the presence of a terminating `!`
517/// (or lack thereof)** to determine whether the given derive macro is a classic
518/// procedural macro one or a `macro_rules!` one.
519pub use ::macro_rules_attribute_proc_macro::derive;
520
521attribute_alias! {
522 #[apply(this_macro_is_private!)] =
523 #[doc(hidden)]
524 /// Not part of the public API
525 #[macro_export]
526 ;
527}
528
529mod nested_derive {
530 //! Inlined mini-version of `::nested_derive`.
531 #[crate::apply(this_macro_is_private!)]
532 macro_rules! ඞ_nested_derive {
533 (
534 #[derive( $($Derives:tt)* )]
535 $($rest:tt)*
536 ) => (
537 #[$crate::derive( $($Derives)* )]
538 #[$crate::apply($crate::ඞ_dalek_EXTERMINATE!)]
539 $($rest)*
540 );
541 }
542
543 // Ideally this would have been `dalek_☃_EXTERMINATE`, since the snowman
544 // ressembles a Dalek more, which is a paramount aspect of this hidden macro
545 // but for some reason Rust despises snowmen even though there are
546 // ඞ-infected identifiers among (s)us…
547 #[crate::apply(this_macro_is_private!)]
548 macro_rules! ඞ_dalek_EXTERMINATE {( $it:item ) => ()}
549}
550
551#[doc(hidden)] /** Not part of the public API */ pub
552mod ඞ {
553 pub use {
554 ::paste::paste,
555 };
556}