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 {}