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}