named_generics_bundle/
_lib.rs

1//! [`named_generics_bundle`]: `named_generics_bundle`
2#![doc = include_str!("../README.md")]
3#![no_std]
4#![forbid(unsafe_code)]
5#![allow(unused_braces)]
6
7/// Main macro, entrypoint to the features of the crate.
8///
9/// See the [main-level docs][`crate`] for more contextual information about this attribute.
10///
11/// # Usage
12///
13/// Basic:
14///
15/// ```rust
16/// # use ::named_generics_bundle::named_generics_bundle;
17/// # use Sized as SomeBounds;
18/// #
19/// #[named_generics_bundle]
20/// trait SomeTrait {
21///     type SomeAssocType: SomeBounds + Clone;
22/// }
23///
24/// fn some_api<S: SomeTrait>(nameable: S::SomeAssocType) {
25///     // Properly implied bounds.
26///     nameable.clone();
27/// }
28///
29/// /// We shall have `Example: SomeTrait + Sized + AllStdDeriveTraits`
30/// type Example = SomeTrait![
31///     # SomeAssocType = (), /*
32///     SomeAssocType = ...,
33///     # */
34/// ];
35///
36/// some_api::<Example>(
37///     // …,
38///     # (),
39/// );
40/// // or, directly:
41/// some_api::<SomeTrait![SomeAssocType = i32]>(42);
42/// ```
43///
44/// More precisely, regarding the attribute macro invocation:
45///
46/// <details open class="custom"><summary><span class="summary-box"><span>Click to show</span></span></summary>
47///
48/// ```rust
49/// # () /*
50/// /// docs…
51/// #[named_generics_bundle(
52///   $(
53///     // Optional. Path must be an absolute path (leading `crate`).
54///     // It allows making the generated eponymous `SomeTrait!` macro be usable
55///     // anywhere, that is, without having to have `SomeTrait` in the current scope.
56///     //
57///     // The macro will tell you what to put here if you get it wrong 🤓
58///     path_to_this_very_module = crate::path::to::this::very::module,
59///   )?
60///   $(
61///     // Optional. Niche and advanced. Useful when re-exporthing this macro from
62///     // another crate (e.g. through some `#[macro_export]`ed macro).
63///     path_to_named_generics_bundle_crate = ::my_crate::reexports::named_generics_bundle,
64///   )?
65/// )]
66/// $pub:vis
67/// trait SomeTrait $(: 'static)? {
68///   $(
69///     /// docs…
70///     type $EachAssocType:ident $(: $TraitBounds…)?;
71///   )*
72/// }
73/// # */
74/// ```
75///
76/// </details>
77///
78/// # Features
79///
80/// <details open class="custom"><summary><span class="summary-box"><span>Click to hide</span></span></summary>
81///
82///   - ### `MyBundle!` eponymous macro definition
83///
84///     The main point of this all is the definition of the convenience `Eponymous!` macro alongside
85///     the trait definition:
86///
87///     ```rust
88///     #[::named_generics_bundle::named_generics_bundle]
89///     trait MyBundle {
90///         type Foo;
91///         // …
92///     }
93///
94///     // defines an eponymous "type-level-instantiation" macro.
95///     # type Example =
96///     MyBundle![
97///         Foo = i32,
98///         // …
99///     ]
100///     # ;
101///     ```
102///
103///   - ### The `trait` definition remains `dyn`-compatible.
104///
105///     As a matter of fact, this is how the generated `Eponymous![]` macro works under the hood:
106///
107///     ```rust
108///     # () /*
109///     AnnotatedTrait![ A = B, C = D, … ]
110///     // expands to:
111///     PhantomData::<fn(ඞ<()>) -> dyn AnnotatedTrait<ඞ<()>, A = B, C = D, …>>
112///     # */
113///     ```
114///
115///       - Add to this a trivial blanket impl of `AnnotatedTrait` for
116///         `PhantomData<fn(ඞ<()>) -> impl ?Sized + AnnotatedTrait<ඞ<()>>>`, and _voilà_!
117///
118///     In case the `ඞ<…>` wrapper did not give this away, do note that the precise form of this
119///     expansion is **not** guaranteed, and therefore susceptible to change within non-major Semver
120///     bumps, as **it will not be considered a breaking change**: the disclosure of this expansion
121///     is done merely for educational/informative reasons.
122///
123///   - ### Implied Bounds (`Sized + Copy + Clone + Send/Sync + …`)
124///
125///     `T : AnnotatedTrait` entails not only `: Sized`, but also every
126///     stdlib `#[derive()]` trait, for convenient use with such (dumb) derives.
127///
128///     More precisely, using an advanced trick with
129///     [`::implied_bounds`](https://docs.rs/implied_bounds), the macro makes it so the `dyn`-safe
130///     `trait` nonetheless entails the following:
131///
132///     ```rust
133///     # () /*
134///     T : AnnotatedTrait,
135///     // to entail:
136///     T :
137///         Debug +
138///         Copy + // and thus, `Clone`
139///         Default +
140///         Ord + // and thus, `PartialOrd + Eq + PartialEq`,
141///         Hash +
142///         Send + Sync + Unpin +
143///     ,
144///     # */
145///     ```
146///
147/// </details>
148///
149/// # Quirks
150///
151///   - To keep things simple, the attribute rejects trait with generics parameters, or associated
152///     items other than types.
153///
154///   - ## The `path_to_this_very_module = ` attribute arg
155///
156///     The generated `Eponymous!` macro, by default, needs to be in scope to be invoked.
157///     That is, invoking it through some qualified path is most likely to result in a path
158///     resolution error:
159///
160///     ```rust ,compile_fail
161///     mod some_module {
162///         #[::named_generics_bundle::named_generics_bundle]
163///         pub trait Example {}
164///     }
165///
166///     type T = some_module::Example![]; // ❌
167///     #
168///     # fn main() {}
169///     ```
170///
171///     which fails with:
172///
173///     <details class="custom"><summary><span class="summary-box"><span>Click to show</span></span></summary>
174///
175///     ```rust ,ignore
176///     # () /*
177///     error[E0405]: cannot find trait `Example` in this scope
178///       --> src/_lib.rs:185:15
179///        |
180///     7  |     pub trait Example {}
181///        |               ^^^^^^^ not found in this scope
182///     ...
183///     10 | type T = some_module::Example![]; // ❌
184///        |          ----------------------- in this macro invocation
185///        |
186///        = note: this error originates in the macro `some_module::Example` (in Nightly builds, run with -Z macro-backtrace for more info)
187///     # */
188///     ```
189///
190///     </details>
191///
192///     This is not a deliberate choice, but a limitation of the language, wherein a macro
193///     invocation such as that of [`#[named_generics_bundle]`][`named_generics_bundle] is unable to know the full/absolute
194///     [`module_path!()`] whence it has been invoked; and yet such a path would be useful or
195///     even necessary to make an invocation like `some_module::Example![…]` robust.
196///
197///     Indeed, the invocation of `Example![…]` will want to involve, and name, `dyn Example`.
198///
199///       - Either the macro and/or the trait is in scope, and doing `dyn Example` will Just Work™.
200///
201///         This is the usual, happy-case case/scenario.
202///
203///       - Or it won't be in scope, like in this instance, and using a more qualified path, such
204///         as `dyn crate::some_module::Example`, is necessary.
205///
206///     Hence the "need" for the invoker of the attribute macro to provide this `crate::some_module`
207///     information to the macro, which is to be done _via_ the `path_to_this_very_module =`
208///     attribute arg:
209///
210///     ```rust
211///     pub mod some_module {
212///         #[::named_generics_bundle::named_generics_bundle(
213///             path_to_this_very_module = crate::some_module,
214///         )]
215///         pub trait Example {}
216///     }
217///
218///     type T = some_module::Example![]; // ✅
219///     #
220///     # fn main() {}
221///     ```
222///
223///       - Note: [`#[named_generics_bundle]`][`named_generics_bundle] will replace the `crate::`
224///         part of this specifier with `$crate::` so as to make the `Example![]` macro it
225///         generates, resilient to being used across crates / from a downstream dependent crate.
226///
227///   - ## The `path_to_named_generics_bundle_crate = ` attribute arg
228///
229///     Since this macro stems from a `proc-macro = true` backend using a frontend/façade package,
230///     the attribute is unable to have a 100%-resilient way to name, and refer back to, its own
231///     frontend crate items. So unless told how, the attribute has no choice but to assume that
232///     users of the attribute will be direct dependents of `::named_generics_bundle`, resulting in
233///     the expansion involving then some hard-coded `::named_generics_bundle`-prefixes.
234///
235///     This is usally fine, but for the case of a _non-direct_ downstream dependent (which is kind
236///     of the case if a direct dependent `#[macro_export]`s some of our functionality to _deeper_,
237///     non-direct, dependents).
238///
239///     At this point, some re-export of this `::named_generics_bundle` crate must have proven
240///     necessary, from somehere. This is the path to be providing to this attribute args.
241///
242///     ```rust
243///     # pub extern crate named_generics_bundle;
244///     #
245///     #[doc(hidden)] /** Not part of the public API */ pub
246///     mod __internals {
247///         /// 👇 Notice whence (and how) `::named_generics_bundle` is being reëxported
248///         pub use ::named_generics_bundle as nmb;
249///     }
250///
251///     /// Demo
252///     /// ```rust
253///     /// ::your_crate::my_fancy_macro!(); // It Works!
254///     /// ```
255///     #[macro_export]
256///     macro_rules! my_fancy_macro {( ... ) => (
257///         #[$crate::__internals::nmb::named_generics_bundle(
258///             path_to_named_generics_bundle_crate = $crate::__internals::nmb,
259///         )]
260///         trait SomeTrait {
261///             ...
262///         }
263///     )}
264///     #
265///     # fn main() {}
266///     ```
267///
268pub use ::named_generics_bundle_proc_macros::named_generics_bundle;
269
270// macro internals
271#[doc(hidden)] /** Not part of the public API */ pub
272mod ඞ {
273    pub use ::core::{
274        self,
275        cmp::Ord,
276        default::Default,
277        fmt::Debug,
278        hash::Hash,
279        marker::{Copy, Send, Sync, Unpin},
280    };
281    pub use ::implied_bounds::ImpliedPredicate;
282    pub use crate::{
283        const_helpers::*,
284    };
285
286    /// This type is used to convey the notion that users of this attribute are
287    /// not to rely on the blanket impl of:
288    /// `impl Trait for PhantomData<fn() -> ඞ<impl ?Sized + Trait<()>>>`
289    ///
290    /// It effectively is, currently, just an identity type wrapper, but it shall make coherence
291    /// treat the resulting type as being literally any possible type, thereby reducing the risk
292    /// of "breaking changes" should I decide to change what the `Eponymous![]` macro unsugars to.
293    pub type ඞ<T> = <T as Identity>::ItSelf;
294
295    pub trait Identity { type ItSelf : ?Sized; }
296    impl<T : ?Sized> Identity for T { type ItSelf = Self; }
297}
298
299mod const_helpers;
300
301#[doc = include_str!("compile_fail_tests.md")]
302mod _compile_fail_tests {}
303
304#[cfg(any(test, feature = "__internal_testing"))]
305extern crate self as named_generics_bundle;
306
307#[cfg(any(test, feature = "__internal_testing"))]
308pub mod tests;