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