1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
//! Niche and advanced, you can ignore this to begin with.
//! Module for type-equality hacks.
//!
//! In certain scenarios, you may have a `T : ForLt` in scope which you want to
//! constrain to match some specific type when fed some specific lifetime;
//! _e.g._
//!
//! ```rust ,ignore
//! //! pseudo-code
//! <'r, T : ForLt>
//! where
//!     T::Of<'r> = &'r str
//! ```
//!
//! In that case, you can actually just write the corresponding real code:
//!
//! ```rust
//! # use ::higher_kinded_types::ForLt;
//! #
//! fn f<'s, T : ForLt>(s: &'s str)
//! where
//!     T : ForLt<Of<'s> = &'s str>,
//! {
//!     let _: T::Of<'s> = s;
//! }
//! ```
//!
//! which does work 🙂.
//!
//! It even works with higher-order lifetimes!
//!
//! ```rust
//! # use ::higher_kinded_types::ForLt;
//! #
//! fn f<T : ForLt>(s: String)
//! where
//!     T : for<'local> ForLt<Of<'local> = &'local str>,
//! {
//!     let _local: T::Of<'_> = &s;
//! }
//! ```
//!
//! But in other more contrived situations, potentially outside of HKTs
//! altogether, these type equality bounds may be unusable or buggy.
//!
//! In that case, the workaround is to replace type _equality constraints_, with
//! good old _trait bounds_, but with a trait designed so as to nonetheless
//! signify type equality:
//!
//! Hence the trait [`Is`]. Alas, it does come with some caveats, since when
//!
//! ```rust
//! # #[cfg(any)] macro_rules! ignore {
//! T : Is<EqTo = U>,
//! # }
//! ```
//!
//! Rust will nonetheless still be treating `T` and `U` as distinct types.
//!
//! Which is why this module provides helper [`cast_right()`] and [`cast_left()`]
//! functions:
//!
//! ```rust
//! use ::higher_kinded_types::{ForLt, type_eq::{self, Is}};
//!
//! fn f<'a, T : ForLt>(a: &'a str)
//! where
//!     T::Of<'a> : Is<EqTo = &'a str>,
//! {
//!     let _: T::Of<'a> = type_eq::cast_left::<T::Of<'a>>(a);
//! }
//! ```
//!
//! But perhaps more interestingly, [`cast_right()`] and [`cast_left()`] are
//! unable to handle _types depending on `T`_, such as `Vec<T>` _vs._ `Vec<U>`.
//!
//! That's when we'd like to use "generic-_over-a-type_ generics", that is,
//! _type_ GATs!
//!
//! …ish: while they're not fully supported (no ergonomic instantiation), it can
//! be intellectually interesting to notice that once we let go of ergonomics,
//! there can be actual usages of type ~~"HKTs"~~ GATs.
//!
//! See, for instance, [`cast_wrapper_right`] and its documentation example.

use crate::extra_arities::ForTy as ForType;

pub
trait Is {
    type EqTo : ?Sized;
}

impl<T : ?Sized> Is for T {
    type EqTo = Self;
}

/// Given <code>T : [Is]\<EqTo = U\></code>, it allows safely converting any
/// value of type `T` into a value of type `U`.
pub
fn cast_right<T>(it: T)
  -> <T as Is>::EqTo
{
    // For those reading this code and curious about what this function even
    // does (it seems to be a noöp!), it's actually quite subtle:
    //
    //  1. In a non-`: Is`-bounded scenario, Rust knows about the blanket
    //     `T : Is<EqTo = T>` property, and so lets these things type check.
    //
    //     This function body is just one example of it.
    //
    //     These scenarios can be spotted by the need to provide the `as Is>`
    //     when querying the associated type.
    //
    //  2. In a `T : Is<EqTo = U>`-bounded scenario, Rust "forgets" about the
    //     outer blanket impl, which is why it will not type-unify these two
    //     things; on the other hand, it still knows of this generic `cast_right`
    //     function, where it can replace the parameters with the properties
    //     it knows. It thus becomes: `fn cast_right<T>(it: T) -> U;` at the
    //     call-site (remember, the body is type-checked *here*, not at
    //     call-sites), and things Just Work™.
    //
    //     Again, this other scenario can be identified by the fact we can just
    //     write `T::EqTo` (to mean `U`), without needing the `as Is>`
    //     disambiguation 💡
    it
}

/// Like [`cast_right()`], but from `T::EqTo` to `T` this time.
///
/// Given <code>T : [Is]\<EqTo = U\></code>, it allows safely converting any
/// value of type `U` into a value of type `T`.
pub
fn cast_left<T>(it: <T as Is>::EqTo)
  -> T
{
    it
}

/// Given <code>T : [Is]\<EqTo = U\></code>, it allows safely converting any
/// value of type <code>Wrapper[::Of]\<T\></code> into a value of type
/// `Wrapper::Of<U>`.
///
/// [::Of]: ForType
///
/// ```rust
/// use ::higher_kinded_types::{
///     extra_arities::{For, new_For_type},
///     type_eq::{cast_wrapper_right, Is},
/// };
///
/// fn demo<T : Is<EqTo = u32>>(
///     v: Vec<T>,
/// ) -> Vec<u32>
/// {
///     new_For_type! {
///         type Vec_ = For!(<T> = Vec<T>);
///     }
///
///     cast_wrapper_right::<Vec_, T>(v)
/// }
/// ```
pub
fn cast_wrapper_right<Wrapper: ForType, T>(
    it: Wrapper::Of<T>,
) -> Wrapper::Of<<T as Is>::EqTo>
{
    it
}

/// Like [`cast_wrapper_right()`], but from `T::EqTo` to `T` this time.
pub
fn cast_wrapper_left<Wrapper: ForType, T>(
    it: Wrapper::Of<<T as Is>::EqTo>,
) -> Wrapper::Of<T>
{
    it
}