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