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