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}