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}