1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
//! Declarative-macro helpers for phantom-only generic wrappers.
//!
//! Several typed-quantity wrappers in this crate parameterise on a phantom
//! generic (`Position<F: Frame>`, `GravParam<P: Planet>`, `Qty3<D, F>`,
//! `InertiaTensor<F>`, `PlanetFixed<P>`, …). The phantom is zero-sized
//! `PhantomData<G>`, so the storage is structurally `Copy + Clone + Debug +
//! PartialEq` whenever the *non-phantom* payload is. `#[derive(Copy)]` etc.
//! disagree: they unconditionally synthesize `where G: Copy + Clone + Debug +
//! PartialEq`, which is wrong for a phantom-only generic — the wrapper would
//! refuse to compile for any tag that does not opt into those derives, even
//! though the runtime storage never touches a `G` value.
//!
//! Hand-rolling the impls works, but at four sites the boilerplate becomes
//! a maintenance smell. The macros below consolidate it:
//!
//! - [`impl_copy_phantom!`] emits a trivial `impl Copy`.
//! - [`impl_clone_phantom!`] emits `impl Clone` whose `clone` is `*self`
//! (free because the wrapper is `Copy`).
//! - [`impl_partial_eq_phantom!`] emits `impl PartialEq` whose `eq` is the
//! caller-supplied boolean expression. The caller names the bound
//! identifiers (typically `self, other`) so macro-hygiene keeps them
//! reachable inside the body expression.
//! - [`impl_debug_phantom!`] emits `impl core::fmt::Debug` whose `fmt`
//! evaluates the caller-supplied expression. The caller names the
//! `&Self` and `&mut Formatter` identifiers (typically `self, f`) for
//! the same hygiene reason.
//!
//! Both the generics-and-bounds list and the type-argument list are passed
//! in **square brackets** to keep `macro_rules!`'s `tt`-greedy matcher
//! unambiguous when the generics include `?Sized` or `+`-joined bounds. The
//! shape is `impl_*_phantom!([<generics>] Ty [<args>] $extras?)`.
/// Emit `impl Copy` for a phantom-only generic.
///
/// ```ignore
/// impl_copy_phantom!([P: Planet] GravParam[P]);
/// impl_copy_phantom!([D: ?Sized + Dimension, F: Frame] Qty3[D, F]);
/// ```
/// Emit `impl Clone` whose `clone` returns `*self` (free because the
/// wrapper is `Copy`).
///
/// ```ignore
/// impl_clone_phantom!([P: Planet] GravParam[P]);
/// ```
/// Emit `impl PartialEq` whose `eq` is `$body`. The caller names the two
/// `&Self` parameters so they survive macro hygiene.
///
/// ```ignore
/// impl_partial_eq_phantom!(
/// [P: Planet] GravParam[P],
/// |this, other| this.value == other.value
/// );
/// impl_partial_eq_phantom!(
/// [D: ?Sized + Dimension, F: Frame] Qty3[D, F],
/// |this, other| this.x.value == other.x.value
/// && this.y.value == other.y.value
/// && this.z.value == other.z.value
/// );
/// ```
/// Emit `impl core::fmt::Debug` whose `fmt` evaluates `$body`. The caller
/// names the `&Self` receiver and the `&mut Formatter` so they survive
/// macro hygiene.
///
/// The caller-supplied body keeps the per-site format string (which often
/// names the phantom tag via `T::NAME` or `core::any::type_name::<T>()`)
/// visible at the call site rather than hidden in a macro.
///
/// ```ignore
/// impl_debug_phantom!(
/// [P: Planet] GravParam[P],
/// |this, f| write!(f, "GravParam<{}>({} m^3/s^2)", P::NAME, this.value)
/// );
/// ```
pub use ;