typewit/type_fn/
injective.rs

1//! Injective type-level functions
2
3
4use crate::TypeFn;
5
6use core::marker::PhantomData;
7
8/// An  [injective]  type-level function
9/// 
10/// This trait is implemented automatically when both
11/// [`TypeFn`] and [`RevTypeFn`] are implemented, and the function is [injective].
12/// `InjTypeFn` cannot be manually implemented.
13/// 
14/// # Properties
15/// 
16/// These are properties about `InjTypeFn` that users can rely on.
17/// 
18/// For any given `F: InjTypeFn<A> + InjTypeFn<B>` these hold:
19/// 
20/// 1. If `A == B`, then `CallInjFn<F, A> == CallInjFn<F, B>`.
21/// 2. If `CallInjFn<F, A> == CallInjFn<F, B>`, then `A == B`.
22/// 3. If `A != B`, then `CallInjFn<F, A> != CallInjFn<F, B>`.
23/// 4. If `CallInjFn<F, A> != CallInjFn<F, B>`, then `A != B`.
24/// 
25/// 
26/// # Examples
27/// 
28/// ### Macro-based Implementation
29/// 
30/// ```rust
31/// use typewit::{CallInjFn, UncallFn, inj_type_fn};
32/// 
33/// let _: CallInjFn<BoxFn, u32> = Box::new(3u32);
34/// let _: UncallFn<BoxFn, Box<u32>> = 3u32;
35/// 
36/// inj_type_fn!{
37///     struct BoxFn;
38/// 
39///     impl<T: ?Sized> T => Box<T>
40/// }
41/// ```
42/// 
43/// ### Non-macro Implementation
44/// 
45/// ```rust
46/// use typewit::{CallInjFn, RevTypeFn, TypeFn, UncallFn};
47/// 
48/// let _: CallInjFn<BoxFn, u32> = Box::new(3u32);
49/// let _: UncallFn<BoxFn, Box<u32>> = 3u32;
50/// 
51/// 
52/// struct BoxFn;
53///
54/// impl<T: ?Sized> TypeFn<T> for BoxFn {
55///     type Output = Box<T>;
56/// 
57///     // Asserts that this impl of `TypeFn` for `BoxFn` is injective.
58///     const TYPE_FN_ASSERTS: () = { let _: CallInjFn<Self, T>; };
59/// }
60/// 
61/// impl<T: ?Sized> RevTypeFn<Box<T>> for BoxFn {
62///     type Arg = T;
63/// }
64/// 
65/// ```
66/// 
67/// [injective]: mod@crate::type_fn#injective
68pub trait InjTypeFn<A: ?Sized>: TypeFn<A, Output = Self::Ret> + RevTypeFn<Self::Ret, Arg = A> {
69    /// Return value of the function
70    type Ret: ?Sized;
71}
72
73impl<F, A: ?Sized, R: ?Sized> InjTypeFn<A> for F
74where
75    F: TypeFn<A, Output = R>,
76    F: RevTypeFn<R, Arg = A>,
77{
78    type Ret = R;
79}
80
81/// The inverse of [`TypeFn`], 
82/// for getting the argument of a [`TypeFn`](crate::type_fn::TypeFn)
83/// from its return value.
84/// 
85/// # Properties
86/// 
87/// These are properties about `RevTypeFn` that users can rely on.
88/// 
89/// For any given `F: RevTypeFn<R> + RevTypeFn<O>` these hold:
90/// 
91/// 1. If `R == O`, then `UncallFn<F, R> == UncallFn<F, O>`
92/// 
93/// 2. If `R != O`, then `UncallFn<F, R> != UncallFn<F, O>`
94/// 
95/// Disclaimer: this trait **does not** by itself ensure that a function is 
96/// [injective],
97/// since `RevTypeFn<Ret>` can't know if `Self::Arg` is the only argument 
98/// that could produce `Ret`.
99/// 
100/// # Examples
101/// 
102/// ### Macro-based impl
103/// 
104/// ```rust
105/// use std::ops::Range;
106///
107/// use typewit::{RevTypeFn, UncallFn};
108///
109/// let array = [3usize, 5];
110///
111/// // Getting the argument of `ArrayFn` from its return value
112/// let value: UncallFn<ArrayFn<2>, [usize; 2]> = array[0];
113///
114/// assert_eq!(value, 3usize);
115///
116/// typewit::inj_type_fn!{
117///     struct ArrayFn<const N: usize>;
118///     impl<T> T => [T; N]
119/// }
120/// ```
121/// 
122/// ### Manual impl
123/// 
124/// ```rust
125/// use std::ops::Range;
126///
127/// use typewit::{CallInjFn, RevTypeFn, TypeFn, UncallFn};
128///
129/// let array = [3usize, 5];
130///
131/// // Getting the argument of `ArrayFn` from its return value
132/// let value: UncallFn<ArrayFn<2>, [usize; 2]> = array[0];
133///
134/// assert_eq!(value, 3usize);
135///
136/// struct ArrayFn<const N: usize>;
137///
138/// impl<T, const N: usize> TypeFn<T> for ArrayFn<N> {
139///     type Output = [T; N];
140///
141///     // Ensures that this impl of `TypeFn` for `ArrayFn` is injective.
142///     const TYPE_FN_ASSERTS: () = { let _: CallInjFn<Self, T>; };
143/// }
144/// impl<T, const N: usize> RevTypeFn<[T; N]> for ArrayFn<N> {
145///     type Arg = T;
146/// }
147/// ```
148/// 
149/// ### Non-injective function
150/// 
151/// As mentioned above, this trait doesn't make a function [injective].
152/// 
153/// In the example below, `NonInjective` isn't injective, because it maps different 
154/// arguments to the same return value:
155/// 
156/// ```rust
157/// use typewit::{CallFn, RevTypeFn, TypeFn, UncallFn};
158/// 
159/// let _: CallFn<NonInjective, Vec<u8>> = 3u8;
160/// let _: CallFn<NonInjective, String> = 5u8;
161/// 
162/// let _: UncallFn<NonInjective, u8> = ();
163/// 
164/// 
165/// struct NonInjective;
166/// 
167/// impl<T> TypeFn<T> for NonInjective {
168///     type Output = u8;
169/// }
170/// 
171/// impl RevTypeFn<u8> for NonInjective {
172///     type Arg = ();
173/// }
174/// ```
175/// 
176/// [injective]: mod@crate::type_fn#injective
177pub trait RevTypeFn<Ret: ?Sized>: TypeFn<Self::Arg, Output = Ret> {
178    /// The argument to this function with `Ret` as the return value.
179    type Arg: ?Sized;
180}
181
182/// Queries the argument to a `F: `[`TypeFn`] from its return value.
183/// 
184/// # Example
185/// 
186/// ```rust
187/// use typewit::UncallFn;
188/// 
189/// let vect = vec![3u32, 5, 8];
190/// let value: UncallFn<VecFn, Vec<u32>> = vect[1];
191/// assert_eq!(value, 5u32);
192/// 
193/// typewit::inj_type_fn!{
194///     struct VecFn;
195///     impl<T> T => Vec<T>
196/// }
197/// ```
198pub type UncallFn<F, Ret> = <F as RevTypeFn<Ret>>::Arg;
199
200
201/// [`CallFn`](crate::CallFn) with an additional `F:`[`InjTypeFn<A>`] requirement,
202/// which helps with type inference.
203///
204/// # Example
205///
206/// ```rust
207/// use typewit::{InjTypeFn, CallInjFn};
208/// 
209/// // inferred return type
210/// let inferred_ret = upcast(3u8);
211/// assert_eq!(inferred_ret, 3);
212/// 
213/// // inferred argument type
214/// let inferred_arg: u32 = upcast(5);
215/// assert_eq!(inferred_arg, 5);
216/// 
217/// // Because the return type is `CallInjFn<_, I>`,
218/// // this can infer `I` from the return type,
219/// fn upcast<I>(int: I) -> CallInjFn<Upcast, I>
220/// where
221///     Upcast: InjTypeFn<I>,
222///     CallInjFn<Upcast, I>: From<I>,
223/// {
224///     int.into()
225/// }
226/// 
227/// 
228/// typewit::inj_type_fn!{
229///     struct Upcast;
230///     
231///     impl u8 => u16;
232///     impl u16 => u32;
233///     impl u32 => u64;
234///     impl u64 => u128;
235/// }
236/// ```
237/// 
238/// As of October 2023, replacing `CallInjFn` with `CallFn` can cause type inference errors:
239/// 
240/// ```text
241/// error[E0277]: the trait bound `Upcast: TypeFn<{integer}>` is not satisfied
242///   --> src/type_fn/injective.rs:132:32
243///    |
244/// 11 | let inferred_arg: u32 = upcast(5);
245///    |                         ------ ^ the trait `TypeFn<{integer}>` is not implemented for `Upcast`
246///    |                         |
247///    |                         required by a bound introduced by this call
248///    |
249///    = help: the following other types implement trait `TypeFn<T>`:
250///              <Upcast as TypeFn<u16>>
251///              <Upcast as TypeFn<u32>>
252///              <Upcast as TypeFn<u64>>
253///              <Upcast as TypeFn<u8>>
254/// ```
255pub type CallInjFn<F, A> = <F as InjTypeFn<A>>::Ret;
256
257
258macro_rules! simple_inj_type_fn {
259    (
260        impl[$($impl:tt)*] ($arg:ty => $ret:ty) for $func:ty
261        $(where[$($where:tt)*])?
262    ) => {
263        impl<$($impl)*> crate::type_fn::TypeFn<$arg> for $func
264        $(where $($where)*)?
265        {
266            type Output = $ret;
267        }
268
269        impl<$($impl)*> crate::type_fn::RevTypeFn<$ret> for $func
270        $(where $($where)*)?
271        {
272            type Arg = $arg;
273        }
274    };
275} pub(crate) use simple_inj_type_fn;
276
277
278////////////////////////////////////////////////////////////////////////////////
279
280/// Reverses an [`InjTypeFn`], its arguments become return values, 
281/// and its return values become arguments.
282/// 
283/// # Examples
284///
285/// ### Permutations
286///
287/// The different ways this function can be combined with [`CallFn`] and 
288/// [`UncallFn`] 
289///
290/// ```rust
291/// use typewit::type_fn::{CallFn, FnRev, UncallFn};
292/// 
293/// let _: CallFn<FnRev<Swap>, Right> = Left;
294/// let _: UncallFn<    Swap,  Right> = Left;
295/// 
296/// let _: CallFn<        Swap,  Up> = Down;
297/// let _: UncallFn<FnRev<Swap>, Up> = Down;
298/// 
299/// typewit::inj_type_fn!{
300///     struct Swap;
301/// 
302///     impl Left => Right;
303///     impl Up   => Down;
304/// }
305/// 
306/// struct Left;
307/// struct Right;
308/// struct Up;
309/// struct Down;
310/// ```
311/// 
312/// [`CallFn`]: crate::CallFn
313pub struct FnRev<F: ?Sized>(PhantomData<fn() -> F>);
314
315
316impl<F: ?Sized> FnRev<F> {
317    /// Constructs a `FnRev`.
318    pub const NEW: Self = Self(PhantomData);
319}
320
321impl<F> FnRev<F> {
322    /// Constructs a `FnRev` from `&F`
323    pub const fn from_ref(_f: &F) -> Self {
324        Self::NEW
325    }
326}
327
328impl<F, A: ?Sized> TypeFn<A> for FnRev<F>
329where
330    F: RevTypeFn<A>
331{
332    type Output = UncallFn<F, A>;
333}
334
335impl<F, R: ?Sized> RevTypeFn<R> for FnRev<F>
336where
337    F: InjTypeFn<R>
338{
339    type Arg = CallInjFn<F, R>;
340}
341
342#[test]
343fn test_fnrev_equivalence(){
344    fn _foo<A, F: InjTypeFn<A>>() {
345        let _ = crate::TypeEq::<CallInjFn<FnRev<F>, F::Ret>, UncallFn<F, F::Ret>>::NEW;
346        
347        let _ = crate::TypeEq::<UncallFn<FnRev<F>, A>, CallInjFn<F, A>>::NEW;
348    }
349}