higher_kinded_types/
_lib.rs

1//! [ForLifetime]: trait@ForLifetime
2#![doc = include_str!("../README.md")]
3#![no_std]
4#![forbid(unsafe_code)]
5#![allow(type_alias_bounds, uncommon_codepoints, unused_braces)]
6#![allow(
7    // in case `crate::ForLt!` does not resolve, we have the `crate::hkt_macro::*` fallback.
8    macro_expanded_macro_exports_accessed_by_absolute_paths,
9)]
10#![cfg_attr(feature = "better-docs",
11    feature(decl_macro, doc_cfg, trait_alias),
12)]
13#![cfg_attr(feature = "fn_traits",
14    feature(unboxed_closures),
15)]
16
17#[macro_use]
18extern crate macro_rules_attribute;
19
20/// The crate's prelude.
21pub
22mod prelude {
23    #[doc(no_inline)]
24    pub use crate::{
25        advanced::{extra_arities::For, ForLifetimeMaybeUnsized},
26        ForLifetime,
27        ForLifetime as ForLt,
28    };
29    #[doc(inline)]
30    pub use crate::hkt_macro::ForLt;
31}
32
33// macro internals
34#[doc(hidden)] /** Not part of the public API */ pub
35mod ඞ {
36    pub use {
37        ::core, // or `std`
38        crate::{
39            advanced::{
40                extra_arities::{
41                    for_lt_and_lt::WithLifetimes,
42                },
43            },
44        },
45    };
46    #[cfg(feature = "fn_traits")]
47    pub use {
48        crate::{
49            fn_traits::{
50                Input as r#for,
51                Input as __,
52            },
53        },
54    };
55
56    /// Do not use this type!
57    pub
58    struct ForLt<T : ?Sized>(
59        ::core::marker::PhantomData<fn(&()) -> &T>,
60        ǃ,
61    );
62
63    /// Do not use this type!
64    pub
65    struct ForLtAndLt<T : ?Sized>(
66        ::core::marker::PhantomData<fn(&()) -> &T>,
67        ǃ,
68    );
69
70    use ::never_say_never::Never as ǃ;
71}
72
73
74#[cfg_attr(feature = "docs-rs",
75    doc(cfg(advanced)),
76)]
77pub
78mod advanced;
79
80#[cfg(feature = "fn_traits")]
81mod fn_traits;
82
83#[allow(unused_imports)]
84#[doc(inline)]
85pub use hkt_macro::ForLt;
86mod hkt_macro;
87
88mod hkt_muncher;
89
90mod utils;
91
92/// The main trait of the crate. The one expressing `: <'_>`-genericity.
93///
94/// It is expected to be used as a bound on a `<T>` generic parameter,
95/// thereby resulting in a <code><T : [ForLt]></code> generic API, which,
96/// conceptually / sort to speak, is to be read as `<T : <'_>>`.
97///
98/// That is, **a _generic API_ whose generic parameter is, in and of itself,
99/// _generic too_!**
100///
101///   - Such a "generic-generic API" is dubbed _higher-kinded_, which makes a
102///     type such as `struct Example<T: <'_>>` then be dubbed _higher-kinded
103///     type_, or **HKT**, for short.
104///
105///     From there, the whole concept of expressing genericity over
106///     `: <'_>`-generic types can also be associated with the idea and concept
107///     of higher-kinded types, much like the name of this crate indicates.
108///
109///     So, using this HKT terminology for something other than a type taking
110///     a [`: For`-bounded] generic type is, if we are to be pedantic[^haskell]
111///     about the topic, an abuse of terminology (one which I'll probably make
112///     throughout this documentation).
113///
114///
115/// [^haskell]: For Haskell enthusiasts, this [`: For`-bounded]-ness could be
116/// called "Arrow-Kinded", as in, it matches the `… -> *` kind. \
117/// \
118/// Then, an Arrow-Kinded type which has, inside the `…`, yet another
119/// Arrow-Kinded type, is what is called a Higher-Kinded Type: \
120/// \
121///   - "Arrow-Kinded Type": `… -> *`, such as `ForLt!(<'a> = &'a str) : ForLt`.
122///   - Higher-Kinded Type: `(… -> *) -> *`, such as `struct Example<T : ForLt>`.
123///
124/// [`: For`-bounded]: advanced::extra_arities
125///
126/// [ForLt]: trait@ForLt
127/// [`ForLt`]: trait@ForLt
128///
129/// It cannot be manually implemented: the only types implementing this trait
130/// are the ones produced by the [`ForLt!`] macro.
131///
132/// ## HKT Usage
133///
134///  1. Make your API take a generic <code>\<T : [ForLifetime]\></code>
135///     parameter (conceptually, a <code>\<T : [Ofᐸᑊ_ᐳ]\></code> parameter).
136///
137///     Congratulations, you now have a _higher-kinded_ API: your API is
138///     not only generic, but it is also taking a parameter which is, in turn,
139///     generic.
140///
141///  1. #### Callers
142///
143///     Call sites use the [`ForLt!`] macro to produce a type which they
144///     can _and must_ turbofish to such APIs. For instance:
145///
146///       - <code>[ForLt!]\(&str\)</code> for the pervasive reference case
147///         (which could also use the <code>[ForRef]\<str\></code> type alias
148///         to avoid the macro),
149///
150///         or <code>[ForLt!]\(Cow\<\'_, str\>\)</code> for more complex
151///         lifetime-infected types;
152///
153///       - <code>[ForLt!]\(u8\)</code> or other owned types work too: it is not
154///         mandatory, at the call-site, to be lifetime-infected, it is just
155///         _possible_ (maximally flexible API). See [`ForFixed`].
156///
157///  1. #### Callee/API author
158///
159///     Make use of this nested genericity in your API!
160///
161///     Feed, somewhere, a lifetime parameter to this `T`:
162///
163///     ```rust
164///     # #[cfg(any())] macro_rules! ignore {
165///     T::Of<'some_lifetime_param>
166///     # }
167///     ```
168///
169///     There are two situations where this is handy:
170///
171///       - wanting to feed two different lifetimes to `T`:
172///
173///          ```rust
174///          use ::higher_kinded_types::ForLifetime;
175///
176///          struct Example<'a, 'b, T : ForLifetime> {
177///              a: T::Of<'a>,
178///              b: T::Of<'b>,
179///          }
180///          ```
181///
182///       - wanting to "feed a lifetime later" / to feed a
183///         `for<>`-quantified lifetime to your <code>impl [ForLt]</code> type:
184///
185///          ```rust
186///          # #[cfg(any())] macro_rules! ignore {
187///          use ::higher_kinded_types::ForLifetime as Ofᐸᑊ_ᐳ; // hopefully illustrative renaming.
188///
189///          fn slice_sort_by_key<Item, Key : Ofᐸᑊ_ᐳ> (
190///              items: &'_ mut [Item],
191///              mut get_key: impl FnMut(&'_ Item) -> Key::Of<'_>,
192///          )
193///          # }
194///          ```
195///
196///          Full example:
197///
198///          <details class="custom"><summary><span class="summary-box"><span>Click to show</span></span></summary>
199///
200///          ```rust
201///          use ::higher_kinded_types::ForLt;
202///
203///          fn slice_sort_by_key<Item, Key : ForLt> (
204///              items: &'_ mut [Item],
205///              mut get_key: impl for<'it> FnMut(&'it Item) -> Key::Of<'it>,
206///          )
207///          where
208///              for<'it> Key::Of<'it> : Ord,
209///          {
210///              items.sort_by(|a: &'_ Item, b: &'_ Item| <Key::Of<'_>>::cmp(
211///                  &get_key(a),
212///                  &get_key(b),
213///              ))
214///          }
215///
216///          // Demo:
217///          let clients: &mut [Client] = // …;
218///          # &mut []; struct Client { key: String, version: u8 }
219///
220///          slice_sort_by_key::<_, ForLt!(&str)>(clients, |c| &c.key); // ✅
221///
222///          // Important: owned case works too!
223///          slice_sort_by_key::<_, ForLt!(u8)>(clients, |c| c.version); // ✅
224///
225///          # #[cfg(any())] {
226///          // But the classic `sort_by_key` stdlib API fails, since it does not use HKTs:
227///          clients.sort_by_key(|c| &c.key); // ❌ Error: cannot infer an appropriate lifetime for autoref due to conflicting requirements
228///          # }
229///          ```
230///
231///          </details>
232///
233/// ### Wait a moment; this is just a GAT! Why are you talking of HKTs?
234///
235/// Indeed, the definition of the <code>[ForLt]</code> trait is basically that
236/// of a trait featuring the simplest possible GAT:
237///
238/// ```rust
239/// trait Trait { // basic trait
240///     type Assoc<'lt>; // Associated Type which is itself Generic = GAT.
241/// }
242///
243/// struct Struct<'a, 'b, T : Trait> {
244///     a: T::Assoc<'a>,
245///     b: T::Assoc<'b>,
246/// }
247/// ```
248///
249/// Yes, the `: <'_>` signature pattern of HKTs, and GATs, from this point of
250/// view, are quite interchangeable:
251///
252///   - this whole crate is a demonstration of featuring `: <'_>` HKT idioms
253///     through a [`ForLt`] GAT trait (+ some extra `for<>`-quantifications);
254///
255///   - in a world with HKTs and `: <'_>` as a first-class construct, GATs could
256///     then just be HKT Associated Types (HATs instead of GATs 🤠).
257///
258///     ```rust ,ignore
259///     //! pseudo-code!
260///     trait LendingIterator {
261///         type Item: <'_>;
262///
263///         fn next(&mut self) -> Self::Item<'_>;
264///     }
265///     ```
266///
267///       - Real code:
268///
269///         <details class="custom"><summary><span class="summary-box"><span>Click to show</span></span></summary>
270///
271///         ```rust
272///         use ::higher_kinded_types::ForLt;
273///
274///         trait LendingIterator {
275///             /// Look ma, "no" GATs!
276///             type Item: ForLt;
277///
278///             fn next(&mut self) -> <Self::Item as ForLt>::Of<'_>;
279///         }
280///         ```
281///
282///     </details>
283///
284/// In a way, the similarity between these two paradigms is akin to that of
285/// closure _vs._ object in more classic programming: you can always pick some
286/// canonical object interface, say:
287///
288/// ```rust
289/// trait Closure<Args> {
290///     type Ret;
291///
292///     fn call(&self, _: Args) -> Self::Ret;
293/// }
294/// ```
295///
296/// and then use `Closure<Args, Ret = …>` where we currently use
297/// `Fn(Args…) -> Output`: that is, the _canonical_ `Fn…` traits can easily be
298/// polyfilled with any arbitrary trait of our choice featuring the same
299/// functional API (same method signature).
300///
301/// or, _vice versa_, never define custom traits or interfaces, and always
302/// use closures:
303///
304/// ```rust ,ignore
305/// trait Display = Fn(&mut fmt::Formatter<'_>) -> fmt::Result;
306/// // etc.
307/// ```
308///
309///   - The astute reader may notice that we lose the _nominal typing_ aspect
310///     of our current traits, which is what lets us, for instance, distinguish
311///     between `Display` and `Debug`, even if both traits, _structurally_, are
312///     equivalent / have exactly the same function signature.
313///
314///       - In general, Rust traits go way beyond the sheer API of their
315///         methods. They can be used as (sometimes `unsafe`) marker traits, or
316///         other API promises, _etc._
317///
318/// So, closures are just one specific interface/trait shape, which we could use
319/// pervasively everywhere, if we did not mind the loss of "nominal typing" (the
320/// trait name).
321///
322/// But they're actually more: closures would not be near as useful as they are
323/// if we did not have **closure expressions**!
324///
325/// In fact, closure expressions are so handy that nowadays we have a bunch of
326/// `impl Trait` constructors that take the raw/bare API/signature as a closure,
327/// and then wrap it within the "name" of the trait:
328///
329///   - **[`Iterator`]**: from
330///     `FnMut() -> Option<Item>`
331///     using [`iter::from_fn()`][::core::iter::from_fn]
332///   - **[`Future`]**: from
333///     <code>FnMut\(\&mut [Context]\<\'_\>\) -\> [Poll]\<Output\></code>
334///     using [`future::poll_fn()`][::core::future::poll_fn];
335///   - **[`Stream`]**: from
336///     `FnMut(Acc) -> impl Future<Output = (Item, Acc)>`
337///     using [`stream::unfold()`]
338///
339/// [`Future`]: ::core::future::Future
340/// [Context]: ::core::task::Context
341/// [Poll]: ::core::task::Poll
342/// [`Stream`]: https://docs.rs/futures/^0.3.28/futures/stream/trait.Stream.html
343/// [`stream::unfold()`]: https://docs.rs/futures/^0.3.28/futures/stream/fn.unfold.html
344///
345/// And that same difference applies to arbitrary GATs _vs._ [`ForLt`]: the
346/// ability to produce _ad-hoc_ / on-demand <code>impl [ForLt]</code> types /
347/// [`ForLt`] type "expressions", thanks to the [`ForLt!`] macro, is what makes
348/// [`ForLt`] convenient and flexible, _vs._ the overly cumbersome aspect of
349/// manually using custom GATs.
350///
351/// Indeed, compare:
352///
353/// ```rust
354/// trait ForLt {
355///     type Assoc<'lt>;
356/// }
357///
358/// enum StrRef {}
359///
360/// impl ForLt for StrRef {
361///     type Assoc<'lt> = &'lt str;
362/// }
363/// ```
364///
365/// to:
366///
367/// ```rust
368/// # use ::higher_kinded_types::ForLt;
369/// type StrRef = ForLt!(<'lt> = &'lt str);
370/// ```
371///
372/// ### Conclusion
373///
374/// So, to summarize, this <code>[ForLt] = ": \<\'_\>"</code> HKT pattern is just:
375///
376///   - some GAT API having been _canonical_-ized,
377///
378///       - much like how, in the realm of closures, the `Fn(Args…) -> R` was
379///         picked (_vs._ any other signature-equivalent
380///         `Closure<Args, Ret = R>` trait);
381///
382///   - which can be "inhabited" _on demand_ / in an _ad-hoc_ fashion thanks to
383///     the <code>[ForLt!]\(\<\'input\> = Output…\)</code> macro,
384///
385///       - much like how, in the realm of closures, it is done with the
386///         `|input…| output…` closure expressions.
387///
388/// In other words:
389///
390/// > `: <'_>` and HKTs are to GATs what closures are to traits.
391///
392/// (it's the `Fn(Lifetime) -> Type` of the type realm).
393///
394/// ___
395///
396/// Finally, another observation which I find interesting, is that:
397///
398/// ```rust
399/// # use ::higher_kinded_types::ForLt;
400/// #
401/// type A = ForLt!(<'r> = &'r str);
402/// // vs.
403/// type B        <'r> = &'r str;
404/// ```
405///
406/// is an annoying limitation of Rust, which happens to feature a similar
407/// distinction that certain past languages have had between values, and
408/// functions, wherein they were treated separately (rather than as first-class
409/// citizens, _i.e._, like the other values).
410///
411/// In Rust, `type B<'r> = &'r str;` suffers from this same kind of limitation,
412/// only in the type realm this time: `type B<'r> =` is a special construct,
413/// which yields a _"type" constructor_. That is, it yields some syntax, `B`, to
414/// which we can feed a lifetime `'lt`, by writing `B<'lt>`, so as to end up
415/// with a _type_.
416///
417/// **But `B`, in and of itself, _is not a type_**, even if we often call it a
418/// "generic type" by abuse of terminology.
419///
420/// Which is why it cannot be fed, _alone_, to some type-generic API that would
421/// want to be the one feeding the lifetime parameter: it does not play well
422/// with "generic generics"!
423///
424/// In this example, the only true "generic _type_", that is, the _type_ which
425/// is, itself, lifetime-generic, is `A`.
426///
427/// This is where [`ForLt!`] and HKTs, thus, shine.
428pub
429trait ForLifetime : seal::WithLifetimeForAny {
430    /// "Instantiate lifetime" / "apply/feed lifetime" operation:
431    ///
432    ///   - Given <code>\<T : [ForLt]\></code>,
433    ///
434    ///     `T::Of<'lt>` stands for the HKT-conceptual `T<'lt>` type.
435    ///
436    /// [ForLt]: trait@ForLt
437    type Of<'lt>;
438}
439
440mod seal {
441    pub trait WithLifetimeForAny {}
442    impl<T : ?Sized + for<'any> crate::advanced::WithLifetime<'any>> WithLifetimeForAny for T {}
443}
444
445/// Shorthand alias.
446#[doc(no_inline)]
447pub use ForLifetime as ForLt;
448
449crate::utils::cfg_match! {
450    feature = "better-docs" => (
451        /// <code>: [Ofᐸᑊ_ᐳ]</code> is a hopefully illustrative syntax that
452        /// serves as an alias for <code>: [ForLt]</code>.
453        ///
454        /// [ForLt]: trait@ForLt
455        ///
456        /// When trying to teach the notion of a HKT / "generic generic API" to
457        /// somebody who has never run into it, _e.g._, in introductory
458        /// documentation, blog posts, _etc._, the <code>: [Ofᐸᑊ_ᐳ]</code>
459        /// syntax ought to be more _intuitive_:
460        ///
461        /// ```rust
462        /// use ::higher_kinded_types::*;
463        ///
464        /// struct Example<'a, 'b, T : Ofᐸᑊ_ᐳ> {
465        ///     a: T::Of<'a>,
466        ///     b: T::Of<'b>,
467        /// }
468        /// ```
469        ///
470        ///   - (the idea being that `: Ofᐸᑊ_ᐳ` looks quite a bit like `: Of<'_>`).
471        ///
472        ///   - ⚠️ real code should nonetheless be using the <code>: [ForLt]</code>
473        ///     syntax: ASCII characters are easier to type with a standard
474        ///     keyboard layout, contrary to `Ofᐸᑊ_ᐳ`, which will probably require
475        ///     copy-pasting.
476        #[doc(cfg(educational))]
477        pub trait Ofᐸᑊ_ᐳ = ForLt;
478    );
479
480    _ => (
481        mod r#trait {
482            #![allow(unused)]
483            pub use super::*;
484            macro_rules! __ {() => ()}
485            use __ as ForLt;
486        }
487
488        pub trait Ofᐸᑊ_ᐳ where Self : ForLt {}
489        impl<T : ?Sized> Ofᐸᑊ_ᐳ for T where Self : ForLt {}
490    );
491}
492
493/// <code>[ForFixed]\<T\></code> is a macro-free alias for
494/// <code>[ForLt!]\(\<\'_unused\> = T\)</code>.
495///
496/// To be used when the generic lifetime parameter is to be ignored, while
497/// calling into some HKT API.
498pub
499type ForFixed<T : Sized> = ForLt!(T);
500
501/// <code>[ForRef]\<T\></code> is a macro-free alias for
502/// <code>[ForLt!]\(\<\'any\> = \&\'any T\)</code>.
503pub
504type ForRef<T : ?Sized> = ForLt!(&'_ T);
505
506/// <code>[ForRefMut]\<T\></code> is a macro-free alias for
507/// <code>[ForLt!]\(\<\'any\> = \&\'any mut T\)</code>.
508pub
509type ForRefMut<T : ?Sized> = ForLt!(&'_ mut T);
510
511#[cfg(feature = "ui-tests")]
512#[doc = include_str!("compile_fail_tests.md")]
513mod _compile_fail_tests {}