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/// Also derives [`Custom`] to allow using `#[custom(...)]` and `#[derive_args(...)]`
197/// as derive helpers.
198///
199/// ## Examples
200///
201/// ### Implementing `Into<Int>` for a given `#[repr(Int)]` `enum`:
202///
203/** ```rust
204#[macro_use]
205extern crate macro_rules_attribute;
206
207macro_rules! ToInteger {(
208    #[repr($Int:ident)]
209    $(#[$enum_meta:meta])*
210    $pub:vis
211    enum $Enum:ident {
212        $(
213            $Variant:ident $(= $value:expr)?
214        ),* $(,)?
215    }
216) => (
217    impl ::core::convert::From<$Enum> for $Int {
218        #[inline]
219        fn from (x: $Enum)
220          -> Self
221        {
222            x as _
223        }
224    }
225)}
226
227#[macro_rules_derive(ToInteger)] // or `#[macro_rules_derive(ToInteger!)]`
228#[repr(u32)]
229enum Bool {
230    False,
231    True,
232}
233
234fn main ()
235{
236    assert_eq!(u32::from(Bool::False), 0);
237    assert_eq!(u32::from(Bool::True), 1);
238    // assert_eq!(u8::from(Bool::False), 0);
239    // ^ error[E0277]: the trait bound `u8: std::convert::From<main::Bool>` is not satisfied
240}
241``` */
242///
243/// ## Difference with <code>#\[[derive]\]</code>
244///
245/// <code>#\[[macro_rules_derive]\]</code> is specifically intended to be used
246/// with `macro_rules!`-based derives:
247///
248///   - it won't accept classic derives;
249///
250///   - thanks to that, the trailing `!` on the macro name is not mandatory.
251///
252/// For <code>#\[[derive]\]</code>, it's exactly the opposite.
253pub use ::macro_rules_attribute_proc_macro::macro_rules_derive;
254
255/// Convenience macro to define new derive aliases.
256///
257/// The so-defined macros are intended to be used by
258/// <code>#\[[macro_rules_derive]]</code> or this crate's
259/// <code>#\[[derive]]</code>.
260///
261/// ## Examples
262///
263/** ```rust
264# fn main () {}
265#[macro_use]
266extern crate macro_rules_attribute;
267
268derive_alias! {
269    #[derive(Copy!)] = #[derive(Clone, Copy)];
270    #[derive(Eq!)] = #[derive(PartialEq, Eq)];
271    #[derive(Ord!)] = #[derive(Eq!, PartialOrd, Ord)];
272}
273
274#[derive(Debug, Copy!, Ord!)]
275struct Foo {
276    // …
277}
278
279// Note: this defines `Copy!`, `Eq!` and `Ord!` as properly scoped
280// `crate`-local macros.
281mod example {
282    use super::Copy;
283
284    #[derive(Copy!, super::Eq!)]
285    struct Bar;
286}
287``` */
288///
289/** ```rust
290# fn main () {}
291#[macro_use]
292extern crate macro_rules_attribute;
293
294use ::core::{fmt::Debug, hash::Hash};
295
296/// Trait alias pattern: `T : TheUsualSuspects ⇔ T : Debug + Copy + Ord + Hash`.
297trait TheUsualSuspects
298where // `⇒` direction
299    Self : Debug + Copy + Ord + Hash,
300{}
301impl<T : ?Sized> TheUsualSuspects for T
302where // `⇐` direction
303    Self : Debug + Copy + Ord + Hash,
304{}
305
306derive_alias! {
307    #[derive(TheUsualSuspects!)] = #[derive(
308        Debug,
309        Copy,   Clone,
310        Ord,    PartialOrd, Eq, PartialEq,
311        Hash,
312    )];
313}
314
315#[derive(TheUsualSuspects!)]
316struct KeyserSöze;
317
318const _: () = {
319    fn compile_time_assert_impls<T : ?Sized> ()
320    where
321        T : TheUsualSuspects,
322    {}
323
324    let _ = compile_time_assert_impls::<KeyserSöze>;
325};
326``` */
327///
328/// ### Caveat regarding derive helpers (inert-made attributes)
329///
330/// <details><summary>Click to see</summary>
331///
332/// Some derive attributes (such as `{De,}Serialize`), can involve helper
333/// attributes (such as `#[serde]`).
334/// This yields
335/// <a href="https://doc.rust-lang.org/1.60.0/reference/attributes.html#active-and-inert-attributes" target="_blank">inert</a>
336/// derive-<a href="https://doc.rust-lang.org/1.60.0/reference/procedural-macros.html#derive-macro-helper-attributes" target="_blank">helper-attributes</a>,
337/// which represent a _semantic_ aspect of the derive that
338/// **non-compiler-blessed macros such as this one cannot possibly know about**.
339///
340/// This makes aliasing such derives problematic, **since the `derive` aliases
341/// won't be able to handle the helper attributes**.
342///
343/** ```rust ,compile_fail
344# fn main () {}
345#[macro_use]
346extern crate macro_rules_attribute;
347
348derive_alias! {
349    #[derive(Serde!)] = #[derive(::serde::Deserialize, ::serde::Serialize)];
350}
351
352#[derive(Serde!)]
353#[serde(rename_all = "snake_case")] // Error, unknown `#[serde]` attribute
354struct Mejrs {
355    swaginess: u8,
356}
357``` */
358///
359/// The above, for instance, yields something along the lines of:
360///
361/** ```rust
362# #[cfg(any())] macro_rules! ignore {
363 error: cannot find attribute "serde" in this scope
364   --> src/lib.rs:11:3
365    |
366 11 | #[serde(rename_all = "snake_case")]
367    |   ^^^^^
368    |
369    = note: "serde" is in scope, but it is a crate, not an attribute
370# }
371``` */
372///
373/// The only solution is to forgo the niceties of a `derive_alias!`, and define
374/// your own <code>#\[[apply]\]</code>-able `macro_rules_attribute` that aliases
375/// the `#[derive(…)]` attribute as a whole. [`attribute_alias!`] can come in
376/// handy in such situations:
377///
378/** ```rust
379# fn main () {}
380#[macro_use]
381extern crate macro_rules_attribute;
382
383attribute_alias! {
384    #[apply(derive_Serde)] = #[derive(::serde::Deserialize, ::serde::Serialize)];
385}
386
387#[apply(derive_Serde)]
388#[serde(rename_all = "snake_case")] // OK
389struct Mejrs {
390    swaginess: u8,
391}
392``` */
393///
394/// ___
395///
396/// </details>
397#[macro_export]
398macro_rules! derive_alias {(
399    $(
400        #[derive($MacroName:ident !)] = #[derive($($derives:tt)*)];
401    )*
402) => (
403    $crate::ඞ_with_dollar! {( $_:tt ) => (
404        $crate::ඞ::paste! {
405            $(
406                // To avoid ambiguities with what the re-export
407                // refers to, let's use a hopefully unused name.
408                //
409                // Indeed, eponymous derive macros in scope such as those
410                // from the prelude would otherwise cause trouble with the
411                // re-export line.
412                #[allow(nonstandard_style)]
413                macro_rules! [< $MacroName __derive_macro >] {(
414                    $_($item:tt)*
415                ) => (
416                    $crate::ඞ_nested_derive! {
417                        #[derive($($derives)*)]
418                        $_($item)*
419                    }
420                )}
421                #[allow(unused_imports)]
422                pub(in crate) use [< $MacroName __derive_macro >] as $MacroName;
423            )*
424        }
425    )}
426)}
427
428
429/// Convenience macro to define new attribute aliases.
430///
431/// The so-defined macros are intended to be used by <code>#\[[apply]]</code>.
432///
433/// ## Examples
434///
435/** ```rust
436# fn main () {}
437#[macro_use]
438extern crate macro_rules_attribute;
439
440attribute_alias! {
441    #[apply(complex_cfg)] = #[cfg(
442        any(
443            test,
444            doc,
445            all(
446                feature = "some very complex cfg",
447                target_arch = "…",
448            ),
449        )
450    )];
451
452    #[apply(NOT_PART_OF_THE_PUBLIC_API!)] =
453        /// Not part of the public API
454        #[doc(hidden)]
455    ;
456}
457
458#[apply(complex_cfg)]
459struct Foo {
460    // …
461}
462
463#[apply(NOT_PART_OF_THE_PUBLIC_API!)]
464pub mod __macro_internals {
465    // …
466}
467``` */
468///
469#[macro_export]
470macro_rules! attribute_alias {(
471    $(
472        #[apply($name:ident $(!)?)] = $( #[$($attrs:tt)*] )+;
473    )*
474) => (
475    $(
476        $crate::ඞ_with_dollar! {( $_:tt ) => (
477            // Let's not do the paste + module + re-export dance here since it
478            // is less likely for an attribute name to collide with a prelude item.
479            #[allow(nonstandard_style)]
480            macro_rules! $name {( $_($item:tt)* ) => (
481             $( #[$($attrs)*] )+
482                $_($item)*
483            )}
484            #[allow(unused_imports)]
485            pub(in crate) use $name;
486        )}
487    )*
488)}
489
490#[doc(hidden)] /** Not part of the public API*/ #[macro_export]
491macro_rules! ඞ_with_dollar {( $($rules:tt)* ) => (
492    macro_rules! __emit__ { $($rules)* }
493    __emit__! { $ }
494)}
495
496/// Like <code>#\[[macro_rules_derive]\]</code>, but for allowing to be
497/// used to shadow [the "built-in" `#[derive]` attribute][1] (on Rust ≥ 1.57.0).
498///
499/// [1]: https://doc.rust-lang.org/stable/core/prelude/v1/macro.derive.html
500///
501/// That is, it is made a bit more lenient to allow for things such as:
502/** ```rust
503#[macro_use]
504extern crate macro_rules_attribute;
505
506derive_alias! {
507    #[derive(Eq!)] = #[derive(PartialEq, Eq)];
508}
509
510#[derive(Debug, Eq!)]
511struct Foo;
512
513fn main ()
514{
515    assert_eq!(Foo, Foo);
516}
517``` */
518///
519/// This is achieved thanks to **checking for the presence of a terminating `!`
520/// (or lack thereof)** to determine whether the given derive macro is a classic
521/// procedural macro one or a `macro_rules!` one.
522///
523/// Also derives [`Custom`] to allow using `#[custom(...)]` and `#[derive_args(...)]`
524/// as derive helpers.
525pub use ::macro_rules_attribute_proc_macro::derive;
526
527/// No-op macro that is automatically derived with [`derive`] or [`macro_rules_derive`]
528/// to allow using the `#[custom(...)]` and `#[derive_args(...)]` attribute.
529///
530/// See <https://github.com/danielhenrymantilla/macro_rules_attribute-rs/issues/9> for more info.
531pub use ::macro_rules_attribute_proc_macro::Custom;
532
533attribute_alias! {
534    #[apply(this_macro_is_private!)] =
535        #[doc(hidden)]
536        /// Not part of the public API
537        #[macro_export]
538    ;
539}
540
541mod nested_derive {
542    //! Inlined mini-version of `::nested_derive`.
543    #[crate::apply(this_macro_is_private!)]
544    macro_rules! ඞ_nested_derive {
545        (
546            #[derive( $($Derives:tt)* )]
547            $($rest:tt)*
548        ) => (
549            #[$crate::derive( $($Derives)* )]
550            #[$crate::apply($crate::ඞ_dalek_EXTERMINATE!)]
551            $($rest)*
552        );
553    }
554
555    // Ideally this would have been `dalek_☃_EXTERMINATE`, since the snowman
556    // ressembles a Dalek more, which is a paramount aspect of this hidden macro
557    // but for some reason Rust despises snowmen even though there are
558    // ඞ-infected identifiers among (s)us…
559    #[crate::apply(this_macro_is_private!)]
560    macro_rules! ඞ_dalek_EXTERMINATE {( $it:item ) => ()}
561}
562
563#[doc(hidden)] /** Not part of the public API */ pub
564mod ඞ {
565    pub use {
566        ::paste::paste,
567    };
568}