typewit/
type_eq.rs

1use crate::{
2    type_fn::{self, CallFn, InvokeAlias, RevTypeFn, TypeFn, UncallFn}, 
3    MakeTypeWitness, TypeWitnessTypeArg,
4};
5
6use crate::const_marker::Usize;
7
8
9
10use core::{
11    cmp::{Ordering, Eq, Ord, PartialEq, PartialOrd},
12    default::Default,
13    hash::{Hash, Hasher},
14    fmt::{self, Debug},
15};
16
17#[cfg(feature = "alloc")]
18use alloc::boxed::Box;
19
20crate::type_eq_ne_guts::declare_helpers!{
21    $
22    TypeEq
23    TypeFn
24    CallFn
25}
26
27crate::type_eq_ne_guts::declare_zip_helper!{
28    $ TypeEq
29}
30
31// Equivalent to `type_eq.zip(other_type_eq).project::<Func>()`,
32// defined to ensure that methods which do zip+project have 0 overhead in debug builds.
33macro_rules! zip_project {
34    // Since `$L0`, `$L1`,`$R0`, and `$R1` are all used only once,
35    // it's safe to declare them as `:ty` (safe against malicious type macros).
36    (
37        $left_type_eq:expr,
38        $right_type_eq:expr,
39        $F: ty,
40        ($L0:ty, $R0:ty),
41        ($L1:ty, $R1:ty),
42    ) => ({
43        __ZipProjectVars::<$F, $L0, $R0, $L1, $R1> {
44            left_te: $left_type_eq,
45            right_te: $right_type_eq,
46            projected_te: {
47                // SAFETY: 
48                // `TypeEq<$L0, $R0>` and `TypeEq<$L1, $R1>` 
49                // implies `TypeEq<($L0, $L1), ($R0, $R1)>`,
50                // 
51                // Using `$F` only once, as a type argument,
52                // to protect against type-position macros that expand to 
53                // different types on each use.
54                unsafe {
55                    TypeEq::new_unchecked()
56                }
57            }
58        }.projected_te
59    });
60}
61
62struct __ZipProjectVars<F, L0, R0, L1, R1> 
63where
64    F: TypeFn<(L0, L1)> + TypeFn<(R0, R1)>
65{
66    #[allow(dead_code)]
67    left_te: TypeEq<L0, R0>,
68
69    #[allow(dead_code)]
70    right_te: TypeEq<L1, R1>,
71
72    //         (TypeEq<L0, R0>, TypeEq<L1, R1>) 
73    // implies TypeEq<(L0, L1), (R0, R1)> 
74    // implies TypeEq<CallFn<F, (L0, L1)>, CallFn<F, (R0, R1)>>
75    projected_te: TypeEq<CallFn<F, (L0, L1)>, CallFn<F, (R0, R1)>>,
76}
77
78
79/// Constructs a [`TypeEq<T, T>`](TypeEq)
80/// 
81/// # Example
82/// 
83/// ```rust
84/// use typewit::{MakeTypeWitness, TypeWitnessTypeArg, TypeEq, type_eq};
85/// 
86/// assert_eq!(ascii_to_upper(b'a'), b'A');
87/// assert_eq!(ascii_to_upper(b'f'), b'F');
88/// assert_eq!(ascii_to_upper(b'B'), b'B');
89/// assert_eq!(ascii_to_upper(b'0'), b'0');
90/// 
91/// assert_eq!(ascii_to_upper('c'), 'C');
92/// assert_eq!(ascii_to_upper('e'), 'E');
93/// assert_eq!(ascii_to_upper('H'), 'H');
94/// assert_eq!(ascii_to_upper('@'), '@');
95/// 
96/// const fn ascii_to_upper<T>(c: T) -> T 
97/// where
98///     Wit<T>: MakeTypeWitness,
99/// {
100///     match MakeTypeWitness::MAKE {
101///         Wit::U8(te) => {
102///             // `te` is a `TypeEq<T, u8>`, which allows casting between `T` and `u8`.
103///             // `te.to_right(...)` goes from `T` to `u8`
104///             // `te.to_left(...)` goes from `u8` to `T`
105///             te.to_left(te.to_right(c).to_ascii_uppercase())
106///         }
107///         Wit::Char(te) => {
108///             // `te` is a `TypeEq<T, char>`, which allows casting between `T` and `char`.
109///             // `te.to_right(...)` goes from `T` to `char`
110///             // `te.to_left(...)` goes from `char` to `T`
111///             te.to_left(te.to_right(c).to_ascii_uppercase())
112///         }
113///     }
114/// }
115/// 
116/// // This is a type witness
117/// enum Wit<T> {
118///     // this variant requires `T == u8`
119///     U8(TypeEq<T, u8>),
120/// 
121///     // this variant requires `T == char`
122///     Char(TypeEq<T, char>),
123/// }
124/// impl<T> TypeWitnessTypeArg for Wit<T> {
125///     type Arg = T;
126/// }
127/// impl MakeTypeWitness for Wit<u8> {
128///     const MAKE: Self = Self::U8(type_eq());
129/// }
130/// impl MakeTypeWitness for Wit<char> {
131///     const MAKE: Self = Self::Char(type_eq());
132/// }
133/// ```
134/// The code above can be written more concisly using 
135/// the [`polymatch`](crate::polymatch) and [`simple_type_witness`] macros:
136/// ```rust
137/// # use typewit::{MakeTypeWitness, TypeWitnessTypeArg, TypeEq, type_eq};
138/// # 
139/// # assert_eq!(ascii_to_upper(b'a'), b'A');
140/// # assert_eq!(ascii_to_upper(b'f'), b'F');
141/// # assert_eq!(ascii_to_upper(b'B'), b'B');
142/// # assert_eq!(ascii_to_upper(b'0'), b'0');
143/// # 
144/// # assert_eq!(ascii_to_upper('c'), 'C');
145/// # assert_eq!(ascii_to_upper('e'), 'E');
146/// # assert_eq!(ascii_to_upper('H'), 'H');
147/// # assert_eq!(ascii_to_upper('@'), '@');
148/// # 
149/// const fn ascii_to_upper<T>(c: T) -> T 
150/// where
151///     Wit<T>: MakeTypeWitness,
152/// {
153///     // deduplicating identical match arms using the `polymatch` macro.
154///     typewit::polymatch!{MakeTypeWitness::MAKE;
155///         Wit::U8(te) | Wit::Char(te) => te.to_left(te.to_right(c).to_ascii_uppercase())
156///     }
157/// }
158///
159/// // This macro declares a type witness
160/// typewit::simple_type_witness! {
161///     // Declares `enum Wit<__Wit>`
162///     // The `__Wit` type parameter is implicit and always the last generic parameter.
163///     enum Wit {
164///         // this variant requires `__Wit == u8`
165///         U8 = u8,
166///         // this variant requires `__Wit == char`
167///         Char = char,
168///     }
169/// }
170/// ```
171/// note that [`simple_type_witness`] can't replace enums whose 
172/// witnessed type parameter is not the last, 
173/// or have variants with anything but one `TypeEq` field each.
174/// 
175/// [`simple_type_witness`]: crate::simple_type_witness
176#[inline(always)]
177pub const fn type_eq<T: ?Sized>() -> TypeEq<T, T> {
178    TypeEq::NEW
179}
180
181
182// Declaring `TypeEq` in a submodule to prevent "safely" constructing `TypeEq` with
183// two different type arguments in the `crate::type_eq` module.
184mod type_eq_ {
185    use core::{
186        any::{Any, TypeId},
187        marker::PhantomData,
188    };
189
190    /// Value-level proof that `L` is the same type as `R`
191    ///
192    /// This type can be used to prove that `L` and `R` are the same type,
193    /// because it can only be safely constructed with 
194    /// [`TypeEq::<L, L>::NEW`](#associatedconstant.NEW)(or [`new`](#method.new)),
195    /// where both type arguments are the same type.
196    ///
197    /// This type is not too useful by itself, it becomes useful 
198    /// [when put inside of an enum](#polymorphic-branching).
199    ///
200    /// 
201    /// `TypeEq<L, R>` uses the `L` type parameter as the more generic type by convention
202    /// (e.g: `TypeEq<T, char>`).
203    /// This only matters if you're using the type witness traits 
204    /// ([`HasTypeWitness`](crate::HasTypeWitness), 
205    /// [`MakeTypeWitness`](crate::MakeTypeWitness), 
206    ///  [`TypeWitnessTypeArg`](crate::TypeWitnessTypeArg)) with `TypeEq`.
207    ///
208    /// # Soundness
209    /// 
210    /// `TypeEq<L, R>` requires both type arguments to be the same type so that 
211    /// [projecting](Self::project) the type arguments results in the same type for 
212    /// both arguments.
213    /// 
214    /// Unsafely creating a `TypeEq<L, R>` where `L != R` allows
215    /// [transmuting between any two types](#arbitrary-transmute)
216    /// (that is bad).
217    ///
218    /// # Examples
219    /// 
220    /// ### Polymorphic branching
221    /// 
222    /// This example demonstrates how type witnesses can be used to 
223    /// choose between expressions of different types with a constant. 
224    /// 
225    /// ```rust
226    /// use typewit::TypeEq;
227    /// 
228    /// const fn main() {
229    ///     assert!(matches!(choose!(0; b"a string", 2, panic!()), b"a string"));
230    /// 
231    ///     const UNO: u64 = 1;
232    ///     assert!(matches!(choose!(UNO; loop{}, [3, 5], true), [3, 5]));
233    /// 
234    ///     assert!(matches!(choose!(2 + 3; (), unreachable!(), ['5', '3']), ['5', '3']));
235    /// }
236    /// 
237    /// /// Evaluates the argument at position `$chosen % 3`, other arguments aren't evaluated.
238    /// /// 
239    /// /// The arguments can all be different types.
240    /// /// 
241    /// /// `$chosen` must be a `u64` constant.
242    /// #[macro_export]
243    /// macro_rules! choose {
244    ///     ($chosen:expr; $arg_0: expr, $arg_1: expr, $arg_2: expr) => {
245    ///         match Choice::<{$chosen % 3}>::VAL {
246    ///             // `te` (a `TypeEq<T, X>`) allows us to safely go between 
247    ///             // the type that the match returns (its `T` type argument)
248    ///             // and the type of `$arg_0` (its `X` type argument).
249    ///             Branch3::A(te) => {
250    ///                 // `to_left` goes from `X` to `T`
251    ///                 te.to_left($arg_0)
252    ///             }
253    ///             // same as the `A` branch, with a different type for the argument
254    ///             Branch3::B(te) => te.to_left($arg_1),
255    ///             // same as the `A` branch, with a different type for the argument
256    ///             Branch3::C(te) => te.to_left($arg_2),
257    ///         }
258    ///     }
259    /// }
260    /// 
261    /// // This is a type witness
262    /// pub enum Branch3<T, X, Y, Z> {
263    ///     // This variant requires `T == X`
264    ///     A(TypeEq<T, X>),
265    /// 
266    ///     // This variant requires `T == Y`
267    ///     B(TypeEq<T, Y>),
268    /// 
269    ///     // This variant requires `T == Z`
270    ///     C(TypeEq<T, Z>),
271    /// }
272    /// 
273    /// // Used to get different values of `Branch3` depending on `N`
274    /// pub trait Choice<const N: u64> {
275    ///     const VAL: Self;
276    /// }
277    /// 
278    /// impl<X, Y, Z> Choice<0> for Branch3<X, X, Y, Z> {
279    ///     // Because the first two type arguments of `Branch3` are `X`
280    ///     // (as required by the `TypeEq<T, X>` field in Branch3's type definition),
281    ///     // we can use `TypeEq::NEW` here.
282    ///     const VAL: Self = Self::A(TypeEq::NEW);
283    /// }
284    /// 
285    /// impl<X, Y, Z> Choice<1> for Branch3<Y, X, Y, Z> {
286    ///     const VAL: Self = Self::B(TypeEq::NEW);
287    /// }
288    /// 
289    /// impl<X, Y, Z> Choice<2> for Branch3<Z, X, Y, Z> {
290    ///     const VAL: Self = Self::C(TypeEq::NEW);
291    /// }
292    /// 
293    /// ```
294    /// 
295    pub struct TypeEq<L: ?Sized, R: ?Sized>(PhantomData<TypeEqHelper<L, R>>);
296
297    // Declared to work around this error in old Rust versions:
298    // > error[E0658]: function pointers cannot appear in constant functions
299    struct TypeEqHelper<L: ?Sized, R: ?Sized>(
300        #[allow(dead_code)]
301        fn(PhantomData<L>) -> PhantomData<L>,
302        #[allow(dead_code)]
303        fn(PhantomData<R>) -> PhantomData<R>,
304    );
305
306
307    impl<T: ?Sized> TypeEq<T, T> {
308        /// Constructs a `TypeEq<T, T>`.
309        /// 
310        /// # Example
311        /// 
312        /// ```rust
313        /// use typewit::TypeEq;
314        /// 
315        /// assert_eq!(mutate(5, Wit::U32(TypeEq::NEW)), 25);
316        /// 
317        /// assert_eq!(mutate(5, Wit::Other(TypeEq::NEW)), 5);
318        /// assert_eq!(mutate("hello", Wit::Other(TypeEq::NEW)), "hello");
319        /// 
320        /// const fn mutate<W>(val: W, wit: Wit<W>) -> W {
321        ///     match wit {
322        ///         Wit::U32(te) => te.to_left(te.to_right(val) + 20),
323        ///         Wit::Other(_) => val,
324        ///     }
325        /// }
326        /// 
327        /// // This can't be written using the `simple_type_witness` macro because the 
328        /// // type in the `Other` variant overlaps with the other ones.
329        /// enum Wit<W> {
330        ///     U32(TypeEq<W, u32>),
331        ///     Other(TypeEq<W, W>),
332        /// }
333        /// ```
334        /// 
335        pub const NEW: Self = TypeEq(PhantomData);
336    }
337
338    impl TypeEq<(), ()> {
339        /// Constructs a `TypeEq<T, T>`.
340        #[inline(always)]
341        pub const fn new<T: ?Sized>() -> TypeEq<T, T> {
342            TypeEq::<T, T>::NEW
343        }
344    }
345
346    impl<L: ?Sized, R: ?Sized> TypeEq<L, R> {
347        /// Constructs `TypeEq<L, R>` if `L == R`, otherwise returns None.
348        ///
349        /// # Example
350        ///
351        /// ```rust
352        /// use typewit::TypeEq;
353        /// 
354        /// use std::any::Any;
355        /// 
356        /// assert_eq!(sum_u32s(&[3u32, 5, 8]), Some(16));
357        /// assert_eq!(sum_u32s(&[3i32, 5, 8]), None);
358        /// 
359        /// 
360        /// fn sum_u32s<T: Clone + Any>(foo: &[T]) -> Option<u32> {
361        ///     typecast_slice::<T, u32>(foo)
362        ///         .map(|foo: &[u32]| foo.iter().copied().sum())
363        /// }
364        /// 
365        /// fn typecast_slice<T: Any, U: Any>(foo: &[T]) -> Option<&[U]> {
366        ///     struct SliceFn;
367        ///     impl<T> typewit::TypeFn<T> for SliceFn {
368        ///         type Output = [T];
369        ///     }
370        /// 
371        ///     TypeEq::<T, U>::with_any().map(|te: TypeEq<T, U>|{
372        ///         te.map(SliceFn) // TypeEq<[T], [U]>
373        ///           .in_ref()   // TypeEq<&[T]>, &[U]>
374        ///           .to_right(foo) // identity cast from `&[T]` to `&[U]`
375        ///     })
376        /// }
377        /// ```
378        pub fn with_any() -> Option<Self>
379        where
380            L: Sized + Any,
381            R: Sized + Any,
382        {
383            if TypeId::of::<L>() == TypeId::of::<R>() {
384                // SAFETY: the two TypeIds compare equal, so L == R
385                unsafe { Some(TypeEq::new_unchecked()) }
386            } else {
387                None
388            }
389        }
390
391        /// Constructs a `TypeEq<L, R>`.
392        ///
393        /// # Safety
394        ///
395        /// You must ensure that `L` is the same type as `R`.
396        ///
397        /// # Examples
398        ///
399        /// ### Unsound usage
400        /// <span id="arbitrary-transmute"></span>
401        ///
402        /// This example demonstrates why `L == R` is a strict requirement.
403        ///
404        /// ```rust
405        /// use typewit::{TypeEq, TypeFn};
406        ///
407        /// // SAFETY: WRONG! UNSOUND!
408        /// let te: TypeEq<u8, i8> = unsafe{ TypeEq::new_unchecked() };
409        /// 
410        /// // Because `TypeEq<u8, i8>` is incorrect,
411        /// // we get this absurd `TypeEq` from the `project` method.
412        /// let absurd: TypeEq<(), Vec<usize>> = te.project::<Func>();
413        /// 
414        /// // This casts from `()` to `Vec<usize>` (which is UB).
415        /// // Last time I tried uncommenting this, it killed the test runner.
416        /// // absurd.to_right(()); 
417        /// 
418        /// struct Func;
419        /// impl TypeFn<u8> for Func { type Output = (); }
420        /// impl TypeFn<i8> for Func { type Output = Vec<usize>; }
421        ///
422        ///
423        /// ```
424        ///
425        #[inline(always)]
426        pub const unsafe fn new_unchecked() -> TypeEq<L, R> {
427            TypeEq(PhantomData)
428        }
429    }
430}
431pub use type_eq_::TypeEq;
432
433impl<L: ?Sized, R: ?Sized> Copy for TypeEq<L, R> {}
434
435impl<L: ?Sized, R: ?Sized> Clone for TypeEq<L, R> {
436    fn clone(&self) -> Self {
437        *self
438    }
439}
440
441impl<L: ?Sized, R: ?Sized> TypeEq<L, R> {
442    /// Converts this `TypeEq` into a [`TypeCmp`](crate::TypeCmp)
443    /// 
444    /// # Example
445    /// 
446    /// ```rust
447    /// use typewit::{TypeCmp, TypeEq};
448    /// 
449    /// const TC: TypeCmp<bool, bool> = TypeEq::NEW.to_cmp();
450    /// 
451    /// assert!(matches!(TC, TypeCmp::Eq(_)));
452    /// ```
453    #[inline(always)]
454    pub const fn to_cmp(self) -> crate::TypeCmp<L, R> {
455        crate::TypeCmp::Eq(self)
456    }
457
458    /// Swaps the type parameters of this `TypeEq`
459    /// 
460    /// # Example
461    /// 
462    /// ```rust
463    /// use typewit::TypeEq;
464    /// 
465    /// assert_eq!(flip_bytes([3, 5], TypeEq::NEW), [5, 3]);
466    /// 
467    /// const fn flip_bytes<T>(val: T, te: TypeEq<T, [u8; 2]>) -> T {
468    ///     bar(val, te.flip())
469    /// }
470    /// const fn bar<T>(val: T, te: TypeEq<[u8; 2], T>) -> T {
471    ///     let [l, r] = te.to_left(val);
472    ///     te.to_right([r, l])
473    /// }
474    /// ```
475    /// 
476    #[inline(always)]
477    pub const fn flip(self: TypeEq<L, R>) -> TypeEq<R, L> {
478        // SAFETY: L == R implies R == L
479        unsafe { TypeEq::new_unchecked() }
480    }
481
482    /// Joins this `TypeEq<L, R>` with a `TypeEq<R, O>`, producing a `TypeEq<L, O>`.
483    /// 
484    /// The returned `TypeEq` can then be used to coerce between `L` and `O`.
485    /// 
486    /// # Example
487    /// 
488    /// ```rust
489    /// use typewit::TypeEq;
490    /// 
491    /// assert_eq!(foo(TypeEq::NEW, TypeEq::NEW, Some(3)), Some(3));
492    /// assert_eq!(foo(TypeEq::NEW, TypeEq::NEW, None), None);
493    /// 
494    /// 
495    /// fn foo<L, X>(
496    ///     this: TypeEq<L, Option<X>>,
497    ///     that: TypeEq<Option<X>, Option<u32>>,
498    ///     value: Option<u32>,
499    /// ) -> L {
500    ///     let te: TypeEq<L, Option<u32>> = this.join(that);
501    ///     te.to_left(value)
502    /// }
503    /// 
504    /// ```
505    /// 
506    #[inline(always)]
507    pub const fn join<O: ?Sized>(self: TypeEq<L, R>, _other: TypeEq<R, O>) -> TypeEq<L, O> {
508        // SAFETY: (L == R, R == O) implies L == O
509        unsafe { TypeEq::new_unchecked() }
510    }
511}
512
513impl<L0, R0> TypeEq<L0, R0> {
514    /// Combines this `TypeEq<L0, R0>` with a `TypeEq<L1, R1>`, 
515    /// producing a `TypeEq<(L0, L1), (R0, R1)>`.
516    /// 
517    /// # Alternative
518    /// 
519    /// For an alternative which allows zipping `TypeEq` with any
520    ///  [`BaseTypeWitness`](crate::BaseTypeWitness),
521    /// you can use [`methods::zip2`](crate::methods::zip2)
522    /// (requires the `"rust_1_65"` feature)
523    /// 
524    /// # Example
525    /// 
526    /// This example demonstrates how one can combine two `TypeEq`s to use
527    /// with a multi-parameter type.
528    /// 
529    /// ```rust
530    /// use typewit::{const_marker::Usize, TypeEq, TypeFn};
531    /// 
532    /// assert_eq!(make_foo(TypeEq::NEW, TypeEq::NEW), Foo("hello", [3, 5, 8]));
533    /// 
534    /// const fn make_foo<T, const N: usize>(
535    ///     te_ty: TypeEq<T, &'static str>,
536    ///     te_len: TypeEq<Usize<N>, Usize<3>>,
537    /// ) -> Foo<T, N> {
538    ///     // the type annotations are just for the reader, they can be inferred.
539    ///     let te_pair: TypeEq<(T, Usize<N>), (&str, Usize<3>)> = te_ty.zip(te_len);
540    /// 
541    ///     let te: TypeEq<Foo<T, N>, Foo<&str, 3>> = te_pair.project::<GFoo>();
542    /// 
543    ///     // `te.to_left(...)` here goes from `Foo<&str, 3>` to `Foo<T, N>`
544    ///     te.to_left(Foo("hello", [3, 5, 8]))
545    /// }
546    /// 
547    /// #[derive(Debug, PartialEq)]
548    /// struct Foo<T, const N: usize>(T, [u8; N]);
549    /// 
550    /// typewit::type_fn!{
551    ///     // Type-level function from `(T, Usize<N>)` to `Foo<T, N>`
552    ///     struct GFoo;
553    ///
554    ///     impl<T, const N: usize> (T, Usize<N>) => Foo<T, N>
555    /// }
556    /// ```
557    /// 
558    #[inline(always)]
559    pub const fn zip<L1: ?Sized, R1: ?Sized>(
560        self: TypeEq<L0, R0>,
561        other: TypeEq<L1, R1>,
562    ) -> TypeEq<(L0, L1), (R0, R1)> {
563        zip_impl!{self[L0, R0], other[L1, R1]}
564    }
565
566    /// Combines three `TypeEq<L*, R*>` to produce a
567    /// `TypeEq<(L0, L1, L2), (R0, R1, R2)>`.
568    /// 
569    /// # Alternative
570    /// 
571    /// For an alternative which allows zipping `TypeEq` with two of any
572    ///  [`BaseTypeWitness`](crate::BaseTypeWitness),
573    /// you can use [`methods::zip3`](crate::methods::zip3)
574    /// (requires the `"rust_1_65"` feature)
575    /// 
576    /// # Example
577    /// 
578    /// ```rust
579    /// use typewit::{TypeEq, type_eq};
580    /// 
581    /// use std::cmp::Ordering::{self, Less};
582    /// 
583    /// assert_eq!(make_tuple(type_eq(), type_eq(), type_eq()), (3, "foo", Less));
584    /// 
585    /// fn make_tuple<A, B, C>(
586    ///     te0: TypeEq<A, u8>,
587    ///     te1: TypeEq<B, &str>,
588    ///     te2: TypeEq<C, Ordering>,
589    /// ) -> (A, B, C) {
590    ///     te0.zip3(te1, te2) // returns `TypeEq<(A, B, C), (u8, &str, Ordering)>`
591    ///         .to_left((3, "foo", Less))
592    /// }
593    /// 
594    /// ```
595    pub const fn zip3<L1, R1, L2: ?Sized, R2: ?Sized>(
596        self: TypeEq<L0, R0>,
597        other1: TypeEq<L1, R1>,
598        other2: TypeEq<L2, R2>,
599    ) -> TypeEq<(L0, L1, L2), (R0, R1, R2)> {
600        zip_impl!{
601            self[L0, R0],
602            other1[L1, R1],
603            other2[L2, R2],
604        }
605    }
606
607    /// Combines four `TypeEq<L*, R*>` to produce a
608    /// `TypeEq<(L0, L1, L2, L3), (R0, R1, R2, L3)>`.
609    /// 
610    /// # Alternative
611    /// 
612    /// For an alternative which allows zipping `TypeEq` with three of any
613    ///  [`BaseTypeWitness`](crate::BaseTypeWitness),
614    /// you can use [`methods::zip4`](crate::methods::zip4)
615    /// (requires the `"rust_1_65"` feature)
616    /// 
617    /// # Example
618    /// 
619    /// ```rust
620    /// use typewit::{TypeEq, type_eq};
621    /// 
622    /// use std::cmp::Ordering::{self, Less};
623    /// 
624    /// assert_eq!(
625    ///     make_tuple(type_eq(), type_eq(), type_eq(), type_eq()), 
626    ///     (3, "foo", Less, true),
627    /// );
628    /// 
629    /// fn make_tuple<A, B, C, D>(
630    ///     te0: TypeEq<A, u8>,
631    ///     te1: TypeEq<B, &str>,
632    ///     te2: TypeEq<C, Ordering>,
633    ///     te3: TypeEq<D, bool>,
634    /// ) -> (A, B, C, D) {
635    ///     let te: TypeEq<(A, B, C, D), (u8, &str, Ordering, bool)> = te0.zip4(te1, te2, te3);
636    ///     te.to_left((3, "foo", Less, true))
637    /// }
638    /// 
639    /// ```
640    pub const fn zip4<L1, R1, L2, R2, L3: ?Sized, R3: ?Sized>(
641        self: TypeEq<L0, R0>,
642        other1: TypeEq<L1, R1>,
643        other2: TypeEq<L2, R2>,
644        other3: TypeEq<L3, R3>,
645    ) -> TypeEq<(L0, L1, L2, L3), (R0, R1, R2, R3)> {
646        zip_impl!{
647            self[L0, R0],
648            other1[L1, R1],
649            other2[L2, R2],
650            other3[L3, R3],
651        }
652    }
653
654}
655
656impl<L, R> TypeEq<L, R> {
657    /// Whether `L` is the same type as `R`.
658    /// 
659    /// False positive equality is fine for this associated constant,
660    /// since it's used to optimize out definitely unequal types.
661    const ARE_SAME_TYPE: Amb = {
662        // hacky way to emulate a lifetime-unaware
663        // `TypeId::of<L>() == TypeId::of<R>()`
664        let approx_same_type = {
665            core::mem::size_of::<L>() == core::mem::size_of::<R>()
666                && core::mem::align_of::<L>() == core::mem::align_of::<R>()
667                && core::mem::size_of::<Option<L>>() == core::mem::size_of::<Option<R>>()
668                && core::mem::align_of::<Option<L>>() == core::mem::align_of::<Option<R>>()
669        };
670
671        if approx_same_type {
672            Amb::Indefinite
673        } else {
674            Amb::No
675        }
676    };
677
678
679    /// Hints to the compiler that a `TypeEq<L, R>`
680    /// can only be constructed if `L == R`.
681    ///
682    /// This function takes and returns `val` unmodified.
683    /// This allows returning some value from an expression
684    /// while hinting that `L == R`.
685    ///
686    #[inline(always)]
687    pub const fn reachability_hint<T>(self, val: T) -> T {
688        if let Amb::No = Self::ARE_SAME_TYPE {
689            // safety: `TypeEq<L, R>` requires `L == R` to be constructed
690            unsafe { core::hint::unreachable_unchecked() }
691        }
692
693        val
694    }
695
696    /// A no-op cast from `L` to `R`.
697    /// 
698    /// This cast is a no-op because having a `TypeEq<L, R>` value
699    /// proves that `L` and `R` are the same type.
700    /// 
701    /// # Example
702    /// 
703    /// ```rust
704    /// use typewit::{TypeEq, type_eq};
705    /// 
706    /// use std::cmp::Ordering::{self, *};
707    /// 
708    /// assert_eq!(mutated(Less, Wit::Ord(type_eq())), Greater);
709    /// assert_eq!(mutated(Equal, Wit::Ord(type_eq())), Equal);
710    /// assert_eq!(mutated(Greater, Wit::Ord(type_eq())), Less);
711    /// 
712    /// assert_eq!(mutated(false, Wit::Bool(type_eq())), true);
713    /// assert_eq!(mutated(true, Wit::Bool(type_eq())), false);
714    /// 
715    /// const fn mutated<R>(arg: R, w: Wit<R>) -> R {
716    ///     match w {
717    ///         Wit::Ord(te) => te.to_left(te.to_right(arg).reverse()),
718    ///         Wit::Bool(te) => te.to_left(!te.to_right(arg)),
719    ///     }
720    /// }
721    /// 
722    /// enum Wit<R> {
723    ///     Ord(TypeEq<R, Ordering>),
724    ///     Bool(TypeEq<R, bool>),
725    /// }
726    /// ```
727    /// 
728    #[inline(always)]
729    pub const fn to_right(self, from: L) -> R {
730        self.reachability_hint(());
731
732        // safety: `TypeEq<L, R>` requires `L == R` to be constructed
733        unsafe { crate::__priv_transmute!(L, R, from) }
734    }
735    /// A no-op cast from `R` to `L`.
736    /// 
737    /// This cast is a no-op because having a `TypeEq<L, R>` value
738    /// proves that `L` and `R` are the same type.
739    /// 
740    /// # Example
741    /// 
742    /// ```rust
743    /// use typewit::{TypeEq, type_eq};
744    /// 
745    /// assert_eq!(stuff(Wit::OptSlice(type_eq())), Some(&[3, 5, 8][..]));
746    /// assert_eq!(stuff(Wit::Bool(type_eq())), true);
747    /// 
748    /// const fn stuff<R>(te: Wit<R>) -> R {
749    ///     match te {
750    ///         Wit::OptSlice(te) => te.to_left(Some(&[3, 5, 8])),
751    ///         Wit::Bool(te) => te.to_left(true),
752    ///     }
753    /// }
754    /// 
755    /// enum Wit<R> {
756    ///     OptSlice(TypeEq<R, Option<&'static [u16]>>),
757    ///     Bool(TypeEq<R, bool>),
758    /// }
759    /// ```
760    /// 
761    #[inline(always)]
762    pub const fn to_left(self, from: R) -> L {
763        self.reachability_hint(());
764
765        // safety: `TypeEq<L, R>` requires `L == R` to be constructed
766        unsafe { crate::__priv_transmute!(R, L, from) }
767    }
768}
769
770
771impl<L: ?Sized, R: ?Sized> TypeWitnessTypeArg for TypeEq<L, R> {
772    type Arg = L;
773}
774
775impl<T: ?Sized> MakeTypeWitness for TypeEq<T, T> {
776    const MAKE: Self = Self::NEW;
777}
778
779
780impl<L: ?Sized, R: ?Sized> TypeEq<L, R> {
781    /// Maps the type arguments of this `TypeEq`
782    /// by using the `F` [type-level function](crate::type_fn::TypeFn).
783    /// 
784    /// Use this function over [`project`](Self::project) 
785    /// if you want the type of the passed in function to be inferred.
786    ///
787    /// # Example
788    /// 
789    /// ```rust
790    /// use typewit::{TypeEq, TypeFn};
791    /// 
792    /// assert_eq!(foo(TypeEq::NEW), (false, 5));
793    /// 
794    /// const fn foo<'a, T>(te: TypeEq<u32, T>) -> (bool, T) {
795    ///     // `GPair<bool>` maps `u32` to `(bool, u32)`
796    ///     //           and maps `T`   to `(bool, T)`
797    ///     let map_te: TypeEq<(bool, u32), (bool, T)> = te.map(GPair::<bool>::NEW); 
798    /// 
799    ///     // same as the above, but inferring `GPair`'s generic arguments.
800    ///     let _: TypeEq<(bool, u32), (bool, T)> = te.map(GPair::NEW); 
801    /// 
802    ///     map_te.to_right((false, 5u32))
803    /// }
804    /// 
805    /// // Declares `struct GPair<A>`, a type-level function from `B` to `(A, B)` 
806    /// typewit::type_fn! {
807    ///      struct GPair<A>;
808    /// 
809    ///      impl<B> B => (A, B)
810    /// } 
811    /// ```
812    /// 
813    // #[cfg(feature = "project")]
814    // #[cfg_attr(feature = "docsrs", doc(cfg(feature = "project")))]
815    pub const fn map<F>(
816        self,
817        func: F,
818    ) -> TypeEq<CallFn<InvokeAlias<F>, L>, CallFn<InvokeAlias<F>, R>>
819    where
820        InvokeAlias<F>: crate::TypeFn<L> + crate::TypeFn<R>
821    {
822        core::mem::forget(func);
823        projected_type_cmp!{self, L, R, F}
824    }
825
826    /// Maps the type arguments of this `TypeEq`
827    /// by using the `F` [type-level function](crate::type_fn::TypeFn).
828    /// 
829    /// Use this function over [`map`](Self::map) 
830    /// if you want to specify the type of the passed in function explicitly.
831    /// 
832    /// # Example
833    /// 
834    /// ```rust
835    /// use typewit::{TypeEq, TypeFn};
836    /// 
837    /// assert_eq!(foo(TypeEq::NEW), vec![3u32, 5, 8]);
838    /// 
839    /// fn foo<T>(te: TypeEq<u32, T>) -> Vec<T> {
840    ///     let vec_te: TypeEq<Vec<u32>, Vec<T>> = te.project::<GVec>();
841    ///     vec_te.to_right(vec![3, 5, 8])
842    /// }
843    /// 
844    /// // Declares `GVec`, a type-level function from `T` to `Vec<T>`
845    /// typewit::type_fn!{
846    ///     struct GVec;
847    /// 
848    ///     impl<T> T => Vec<T>
849    /// }
850    /// 
851    /// ```
852    /// 
853    pub const fn project<F>(self) -> TypeEq<CallFn<InvokeAlias<F>, L>, CallFn<InvokeAlias<F>, R>>
854    where
855        InvokeAlias<F>: crate::TypeFn<L> + crate::TypeFn<R>
856    {
857        projected_type_cmp!{self, L, R, F}
858    }
859}
860
861impl<L: ?Sized, R: ?Sized> TypeEq<L, R> {
862    /// Maps the type arguments of this `TypeEq`
863    /// by using the [reversed](crate::RevTypeFn) 
864    /// version of the `F` type-level function.
865    /// 
866    /// Use this function over [`unproject`](Self::unproject) 
867    /// if you want the type of the passed in function to be inferred.
868    /// 
869    /// # Example
870    /// 
871    /// ```rust
872    /// use typewit::{TypeEq, UncallFn};
873    /// 
874    /// assert_eq!(first_int(&[3, 5, 8, 13], TypeEq::NEW), 3);
875    /// 
876    /// const fn first_int<T, const N: usize>(
877    ///     array: &[T; N],
878    ///     te_slice: TypeEq<[T], [u8]>,
879    /// ) -> u8 {
880    ///     let te: TypeEq<T, u8> = te_slice.unmap(SliceFn);
881    ///
882    ///     let te_ref: TypeEq<&T, &u8> = te.in_ref();
883    ///
884    ///     *te_ref.to_right(&array[0])
885    /// }
886    ///
887    /// typewit::inj_type_fn! {
888    ///     struct SliceFn;
889    /// 
890    ///     impl<T> T => [T]
891    /// }
892    /// ```
893    pub const fn unmap<F>(
894        self,
895        func: F,
896    ) -> TypeEq<UncallFn<InvokeAlias<F>, L>, UncallFn<InvokeAlias<F>, R>>
897    where
898        InvokeAlias<F>: RevTypeFn<L> + RevTypeFn<R>
899    {
900        core::mem::forget(func);
901        
902        unprojected_type_cmp!{self, L, R, F}
903    }
904
905    /// Maps the type arguments of this `TypeEq`
906    /// by using the [reversed](crate::RevTypeFn) 
907    /// version of the `F` type-level function.
908    /// 
909    /// Use this function over [`unmap`](Self::unmap) 
910    /// if you want to specify the type of the passed in function explicitly.
911    /// 
912    /// # Example
913    /// 
914    /// ```rust
915    /// use typewit::TypeEq;
916    /// use std::ops::{Range, RangeInclusive as RangeInc};
917    /// 
918    /// assert_eq!(usize_bounds(3..=5, TypeEq::NEW), (3, 5));
919    /// 
920    /// const fn usize_bounds<T>(
921    ///     range: RangeInc<T>,
922    ///     te_range: TypeEq<Range<T>, Range<usize>>,
923    /// ) -> (usize, usize) {
924    ///     let te: TypeEq<T, usize> = te_range.unproject::<RangeFn>();
925    ///     
926    ///     let te_range_inc: TypeEq<RangeInc<T>, RangeInc<usize>> = te.project::<RangeIncFn>();
927    ///     
928    ///     let range: RangeInc<usize> = te_range_inc.to_right(range);
929    ///     
930    ///     (*range.start(), *range.end())
931    /// }
932    /// 
933    /// typewit::inj_type_fn! {
934    ///     struct RangeFn;
935    /// 
936    ///     impl<T> T => Range<T>
937    /// }
938    /// typewit::inj_type_fn! {
939    ///     struct RangeIncFn;
940    /// 
941    ///     impl<T> T => RangeInc<T>
942    /// }
943    /// ```
944    pub const fn unproject<F>(
945        self,
946    ) -> TypeEq<UncallFn<InvokeAlias<F>, L>, UncallFn<InvokeAlias<F>, R>>
947    where
948        InvokeAlias<F>: crate::RevTypeFn<L> + crate::RevTypeFn<R>
949    {
950        unprojected_type_cmp!{self, L, R, F}
951    }
952}
953
954impl<L: ?Sized, R: ?Sized> TypeEq<L, R> {
955    /// Converts a `TypeEq<L, R>` to `TypeEq<&L, &R>`
956    /// 
957    /// # Example
958    /// 
959    /// ```rust
960    /// use typewit::{MakeTypeWitness, TypeEq};
961    /// 
962    /// assert_eq!(get::<u8>(), &3);
963    /// assert_eq!(get::<str>(), "hello");
964    /// 
965    /// 
966    /// const fn get<R: ?Sized>() -> &'static R 
967    /// where
968    ///     Returned<R>: MakeTypeWitness
969    /// {
970    ///     match MakeTypeWitness::MAKE {
971    ///         // `te` is a `TypeEq<R, u8>`
972    ///         Returned::U8(te) => te.in_ref().to_left(&3),
973    ///
974    ///         // `te` is a `TypeEq<R, str>`
975    ///         Returned::Str(te) => te.in_ref().to_left("hello"),
976    ///     }
977    /// }
978    /// 
979    /// typewit::simple_type_witness! {
980    ///     // declares the `enum Returned<R> {` type witness
981    ///     enum Returned {
982    ///         // this variant requires `R == u8`
983    ///         U8 = u8,
984    ///         // this variant requires `R == str`
985    ///         Str = str,
986    ///     }
987    /// }
988    /// ```
989    /// 
990    pub const fn in_ref<'a>(self) -> TypeEq<&'a L, &'a R> {
991        projected_type_cmp!{self, L, R, type_fn::GRef<'a>}
992    }
993
994    crate::utils::conditionally_const!{
995        feature = "rust_1_83";
996
997        /// Converts a `TypeEq<L, R>` to `TypeEq<&mut L, &mut R>`
998        /// 
999        /// # Constness
1000        /// 
1001        /// This requires the `"rust_1_83"` feature to be a `const fn`.
1002        /// 
1003        /// # Example
1004        /// 
1005        /// Because this example calls `in_mut` inside a `const fn`,
1006        /// it requires the `"rust_1_83"` crate feature.
1007        #[cfg_attr(not(feature = "rust_1_83"), doc = "```ignore")]
1008        #[cfg_attr(feature = "rust_1_83", doc = "```rust")]
1009        /// 
1010        /// use typewit::{TypeEq, type_eq};
1011        /// 
1012        /// let foo = &mut Foo { bar: 10, baz: ['W', 'H', 'O'] };
1013        /// 
1014        /// *get_mut(foo, Field::Bar(type_eq())) *= 2;
1015        /// assert_eq!(foo.bar, 20);
1016        /// 
1017        /// assert_eq!(*get_mut(foo, Field::Baz(type_eq())), ['W', 'H', 'O']);
1018        /// 
1019        /// 
1020        /// const fn get_mut<R>(foo: &mut Foo, te: Field<R>) -> &mut R {
1021        ///     match te {
1022        ///         Field::Bar(te) => te.in_mut().to_left(&mut foo.bar),
1023        ///         Field::Baz(te) => te.in_mut().to_left(&mut foo.baz),
1024        ///     }
1025        /// }
1026        /// 
1027        /// struct Foo {
1028        ///     bar: u8,
1029        ///     baz: [char; 3],
1030        /// }
1031        /// 
1032        /// enum Field<R: ?Sized> {
1033        ///     Bar(TypeEq<R, u8>),
1034        ///     Baz(TypeEq<R, [char; 3]>),
1035        /// }
1036        /// ```
1037        /// 
1038        pub fn in_mut['a](self) -> TypeEq<&'a mut L, &'a mut R> {
1039            projected_type_cmp!{self, L, R, type_fn::GRefMut<'a>}
1040        }
1041    }
1042
1043    /// Converts a `TypeEq<L, R>` to `TypeEq<Box<L>, Box<R>>`
1044    /// 
1045    /// # Example
1046    /// 
1047    /// ```rust
1048    /// use typewit::{MakeTypeWitness, TypeEq, type_eq};
1049    /// 
1050    /// use std::any::Any;
1051    /// use std::fmt::Display;
1052    /// 
1053    /// assert_eq!(factory::<dyn Any>().downcast::<u16>().unwrap(), Box::new(1337));
1054    /// assert_eq!(factory::<dyn Display>().to_string(), "hello bob");
1055    /// 
1056    /// fn factory<R: ?Sized>() -> Box<R> 
1057    /// where
1058    ///     Dyn<R>: MakeTypeWitness
1059    /// {
1060    ///     match MakeTypeWitness::MAKE {
1061    ///         // `te` is a `TypeEq<R, dyn Any>`
1062    ///         Dyn::Any(te) => te.in_box().to_left(Box::new(1337u16)),
1063    ///
1064    ///         // `te` is a `TypeEq<R, dyn Display>`
1065    ///         Dyn::Display(te) => te.in_box().to_left(Box::new("hello bob")),
1066    ///     }
1067    /// }
1068    /// 
1069    /// typewit::simple_type_witness! {
1070    ///     // declares the `enum Dyn<R> {` type witness
1071    ///     enum Dyn {
1072    ///         // this variant requires `R == dyn Any`
1073    ///         Any = dyn Any,
1074    ///         // this variant requires `R == dyn Display`
1075    ///         Display = dyn Display,
1076    ///     }
1077    /// }
1078    /// 
1079    /// ```
1080    ///
1081    #[cfg(feature = "alloc")]
1082    #[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
1083    pub const fn in_box(self) -> TypeEq<Box<L>, Box<R>> {
1084        projected_type_cmp!{self, L, R, type_fn::GBox}
1085    }
1086}
1087
1088impl<L: Sized, R: Sized> TypeEq<L, R> {
1089    /// Combines `TypeEq<L, R>` and `TypeEq<Usize<UL>, Usize<UR>>`
1090    /// into `TypeEq<[L; UL], [R; UR]>`
1091    /// 
1092    /// # Alternative
1093    /// 
1094    /// For an alternative which allows passing any
1095    ///  [`BaseTypeWitness`](crate::BaseTypeWitness) for the length,
1096    /// you can use [`methods::in_array`](crate::methods::in_array)
1097    /// (requires the `"rust_1_65"` feature)
1098    /// 
1099    /// 
1100    /// # Example
1101    /// 
1102    /// <details>
1103    /// <summary><b>motivation</b></summary>
1104    /// <p>
1105    /// The safe way to map an array in const fns(on stable Rust in 2023)
1106    /// is to create an array of the returned type with some dummy value,
1107    /// and then fill it in with the desired values.
1108    /// 
1109    /// Because the function in this example takes a `[T; LEN]` where the `T` is generic,
1110    /// it copies the first element of the input array to initialize the returned array,
1111    /// so we must handle empty arrays, 
1112    /// but trying to return an empty array the naive way
1113    /// ```compile_fail
1114    /// # use std::num::Wrapping;
1115    /// # const fn map_wrapping<T: Copy, const LEN: usize>(arr: [T; LEN]) -> [Wrapping<T>; LEN] {
1116    ///     if LEN == 0 {
1117    ///         return [];
1118    ///     }
1119    /// #   unimplemented!()
1120    /// # }
1121    /// ```
1122    /// does not work
1123    /// ```text
1124    /// error[E0308]: mismatched types
1125    ///  --> src/type_eq.rs:827:16
1126    ///   |
1127    /// 4 | const fn map_wrapping<T: Copy, const LEN: usize>(arr: [T; LEN]) -> [Wrapping<T>; LEN] {
1128    ///   |                                                                    ------------------ expected `[Wrapping<T>; LEN]` because of return type
1129    /// 5 |     if LEN == 0 {
1130    /// 6 |         return [];
1131    ///   |                ^^ expected `LEN`, found `0`
1132    ///   |
1133    ///   = note: expected array `[Wrapping<T>; LEN]`
1134    ///              found array `[_; 0]`
1135    /// 
1136    /// ```
1137    /// </p>
1138    /// </details>
1139    /// 
1140    /// This example demonstrates how `in_array` allows one to return an empty array:
1141    /// (this example requires Rust 1.61.0, because it uses trait bounds in const fns)
1142    #[cfg_attr(not(feature = "rust_1_61"), doc = "```ignore")]
1143    #[cfg_attr(feature = "rust_1_61", doc = "```rust")]
1144    /// use typewit::{const_marker::Usize, TypeCmp, TypeEq};
1145    /// 
1146    /// use std::num::Wrapping;
1147    /// 
1148    /// assert_eq!(map_wrapping([""; 0]), []);
1149    /// assert_eq!(map_wrapping([3, 5, 8]), [Wrapping(3), Wrapping(5), Wrapping(8)]);
1150    /// 
1151    /// const fn map_wrapping<T: Copy, const LEN: usize>(arr: [T; LEN]) -> [Wrapping<T>; LEN] {
1152    ///     // `teq` is a `TypeEq<Usize<LEN>, Usize<0>>`
1153    ///     if let TypeCmp::Eq(teq) = Usize::<LEN>.equals(Usize::<0>) {
1154    ///         return TypeEq::new::<Wrapping<T>>()
1155    ///             .in_array(teq) // `TypeEq<[Wrapping<T>; LEN], [Wrapping<T>; 0]>`
1156    ///             .to_left([]);
1157    ///     }
1158    ///     
1159    ///     let mut ret = [Wrapping(arr[0]); LEN];
1160    ///     let mut i = 1;
1161    ///     
1162    ///     while i < LEN {
1163    ///         ret[i] = Wrapping(arr[i]);
1164    ///         i += 1;
1165    ///     }
1166    ///     
1167    ///     ret
1168    /// }
1169    /// ```
1170    #[inline(always)]
1171    pub const fn in_array<const UL: usize, const UR: usize>(
1172        self,
1173        other: TypeEq<Usize<UL>, Usize<UR>>,
1174    ) -> TypeEq<[L; UL], [R; UR]> {
1175        zip_project!{
1176            self,
1177            other,
1178            crate::type_fn::PairToArrayFn,
1179            (L, R),
1180            (Usize<UL>, Usize<UR>),
1181        }
1182    }
1183}
1184
1185enum Amb {
1186    // indefinitely false/true
1187    Indefinite,
1188    // definitely false
1189    No,
1190}
1191
1192
1193
1194impl<T: ?Sized> Default for TypeEq<T, T> {
1195    fn default() -> Self {
1196        Self::NEW
1197    }
1198}
1199
1200impl<L: ?Sized, R: ?Sized> Debug for TypeEq<L, R> {
1201    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1202        f.write_str("TypeEq")
1203    }
1204}
1205
1206impl<L: ?Sized, R: ?Sized> PartialEq for TypeEq<L, R> {
1207    fn eq(&self, _: &Self) -> bool {
1208        true
1209    }
1210}
1211
1212impl<L: ?Sized, R: ?Sized> PartialOrd for TypeEq<L, R> {
1213    fn partial_cmp(&self, _: &Self) -> Option<Ordering> {
1214        Some(Ordering::Equal)
1215    }
1216}
1217
1218impl<L: ?Sized, R: ?Sized> Ord for TypeEq<L, R> {
1219    fn cmp(&self, _: &Self) -> Ordering {
1220        Ordering::Equal
1221    }
1222}
1223
1224impl<L: ?Sized, R: ?Sized> Eq for TypeEq<L, R> {}
1225
1226
1227impl<L: ?Sized, R: ?Sized> Hash for TypeEq<L, R> {
1228    fn hash<H>(&self, _state: &mut H)
1229    where H: Hasher
1230    {}
1231}
1232