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