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}