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