typewit/
type_cmp.rs

1use crate::{TypeEq, TypeNe};
2
3#[cfg(feature = "rust_1_61")]
4use crate::{BaseTypeWitness, MetaBaseTypeWit, SomeTypeArgIsNe};
5
6
7use core::{
8    any::Any,
9    cmp::{Ordering, Eq, Ord, PartialEq, PartialOrd},
10    hash::{Hash, Hasher},
11    fmt::{self, Debug},
12};
13
14/// A witness of whether its `L` and `R` type parameters are the same or different types.
15/// 
16/// # Example
17/// 
18/// ### Custom array creation
19/// 
20/// (this example requires Rust 1.63.0, because of [`core::array::from_fn`]).
21/// 
22#[cfg_attr(not(feature = "rust_1_65"), doc = "```ignore")]
23#[cfg_attr(feature = "rust_1_65", doc = "```rust")]
24/// use typewit::{const_marker::Usize, TypeCmp, TypeEq, TypeNe};
25/// 
26/// let empty: [String; 0] = [];
27/// assert_eq!(ArrayMaker::<String, 0>::empty().make(), empty);
28/// 
29/// assert_eq!(ArrayMaker::<u8, 2>::defaulted().make(), [0u8, 0u8]);
30/// 
31/// assert_eq!(ArrayMaker::with(|i| i.pow(2)).make(), [0usize, 1, 4, 9]);
32/// 
33/// 
34/// enum ArrayMaker<T, const LEN: usize> {
35///     NonEmpty(fn(usize) -> T, TypeNe<[T; LEN], [T; 0]>),
36///     Empty(TypeEq<[T; LEN], [T; 0]>),
37/// }
38/// 
39/// impl<T, const LEN: usize> ArrayMaker<T, LEN> {
40///     pub fn make(self) -> [T; LEN] {
41///         match self {
42///             ArrayMaker::NonEmpty(func, _) => std::array::from_fn(func),
43///             ArrayMaker::Empty(te) => te.to_left([]),
44///         }
45///     }
46/// 
47///     pub const fn defaulted() -> Self 
48///     where
49///         T: Default
50///     {
51///         Self::with(|_| Default::default())
52///     }
53/// 
54///     pub const fn with(func: fn(usize) -> T) -> Self {
55///         match  Usize::<LEN>.equals(Usize::<0>) // : TypeCmp<Usize<LEN>, Usize<0>>
56///             .project::<ArrayFn<T>>() // : TypeCmp<[T; LEN], [T; 0]>
57///         {
58///             TypeCmp::Ne(ne) => ArrayMaker::NonEmpty(func, ne),
59///             TypeCmp::Eq(eq) => ArrayMaker::Empty(eq),
60///         }
61///     }
62/// }
63/// 
64/// impl<T> ArrayMaker<T, 0> {
65///     pub const fn empty() -> Self {
66///         Self::Empty(TypeEq::NEW)
67///     }
68/// }
69/// 
70/// impl<T, const LEN: usize> Copy for ArrayMaker<T, LEN> {}
71/// 
72/// impl<T, const LEN: usize> Clone for ArrayMaker<T, LEN> {
73///     fn clone(&self) -> Self { *self }
74/// }
75/// 
76/// typewit::inj_type_fn! {
77///     // Declares `struct ArrayFn`, which implements `InjTypeFn<Usize<LEN>>`:
78///     // an injective type-level function from `Usize<LEN>` to `[T; LEN]`
79///     struct ArrayFn<T>;
80///     impl<const LEN: usize> Usize<LEN> => [T; LEN]
81/// }
82/// ```
83pub enum TypeCmp<L: ?Sized, R: ?Sized>{
84    /// proof of `L == R`
85    Eq(TypeEq<L, R>),
86    /// proof of `L != R`
87    Ne(TypeNe<L, R>),
88}
89
90impl<L: ?Sized, R: ?Sized> TypeCmp<L, R> {
91    /// Constructs a `TypeCmp<L, R>` by comparing the `L` and `R` types for equality.
92    /// 
93    /// # Example
94    /// 
95    /// ```rust
96    /// use typewit::TypeCmp;
97    /// 
98    /// let eq: TypeCmp<u8, u8> = TypeCmp::with_any();
99    /// assert!(matches!(eq, TypeCmp::Eq(_)));
100    /// 
101    /// let ne = TypeCmp::<u8, i8>::with_any();
102    /// assert!(matches!(ne, TypeCmp::Ne(_)));
103    /// ```
104    #[deprecated = concat!(
105        "fallout of `https://github.com/rust-lang/rust/issues/97156`,",
106        "`TypeId::of::<L>() != TypeId::of::<R>()` does not imply `L != R`"
107    )]
108    pub fn with_any() -> Self
109    where
110        L: Sized + Any,
111        R: Sized + Any,
112    {
113        #[allow(deprecated)]
114        if let Some(equal) = TypeEq::with_any() {
115            TypeCmp::Eq(equal)
116        } else if let Some(unequal) = TypeNe::with_any() {
117            TypeCmp::Ne(unequal)
118        } else {
119            unreachable!()
120        }
121    }
122
123    /// Swaps the type arguments of this `TypeCmp`
124    /// 
125    /// # Example
126    /// 
127    /// ```rust
128    /// use typewit::{TypeCmp, type_ne};
129    /// 
130    /// const TC: TypeCmp<u8, i8> = TypeCmp::Ne(type_ne!(u8, i8));
131    /// 
132    /// const TK: TypeCmp<i8, u8> = TC.flip();
133    /// 
134    /// ```
135    pub const fn flip(self) -> TypeCmp<R, L> {
136        match self {
137            TypeCmp::Eq(te) => TypeCmp::Eq(te.flip()),
138            TypeCmp::Ne(te) => TypeCmp::Ne(te.flip()),
139        }
140    }
141
142    /// Joins this `TypeCmp<L, R>` with a `TypeEq<Q, L>`, producing a `TypeCmp<Q, R>`.
143    /// 
144    /// # Example
145    /// 
146    /// ```rust
147    /// use typewit::{TypeCmp, TypeEq, type_ne};
148    /// 
149    /// const TC: TypeCmp<str, [u8]> = type_ne!(str, [u8]).to_cmp();
150    /// 
151    /// const fn foo<A: ?Sized>(eq: TypeEq<A, str>) {
152    ///     let _tc: TypeCmp<A, [u8]> = TC.join_left(eq);
153    /// }
154    /// ```
155    pub const fn join_left<Q: ?Sized>(self, left: TypeEq<Q, L>) -> TypeCmp<Q, R> {
156        match self {
157            TypeCmp::Eq(te) => TypeCmp::Eq(left.join(te)),
158            TypeCmp::Ne(te) => TypeCmp::Ne(te.join_left(left)),
159        }
160    }
161
162    /// Joins this `TypeCmp<L, R>` with a `TypeEq<R, Q>`, producing a `TypeCmp<L, Q>`.
163    /// 
164    /// # Example
165    /// 
166    /// ```rust
167    /// use typewit::{TypeCmp, TypeEq, type_ne};
168    /// 
169    /// const NE: TypeCmp<String, Vec<u8>> = type_ne!(String, Vec<u8>).to_cmp();
170    /// 
171    /// const fn foo<A>(eq: TypeEq<Vec<u8>, A>) {
172    ///     let _ne: TypeCmp<String, A> = NE.join_right(eq);
173    /// }
174    /// ```
175    pub const fn join_right<Q: ?Sized>(self, right: TypeEq<R, Q>) -> TypeCmp<L, Q> {
176        match self {
177            TypeCmp::Eq(te) => TypeCmp::Eq(te.join(right)),
178            TypeCmp::Ne(te) => TypeCmp::Ne(te.join_right(right)),
179        }
180    }
181
182    /// Converts this `TypeCmp<L, R>` into an `Option<TypeEq<L, R>>`.
183    /// 
184    /// # Example
185    /// 
186    /// ```rust
187    /// use typewit::{TypeCmp, TypeEq, type_ne};
188    /// 
189    /// let eq: TypeCmp<u8, u8> = TypeCmp::Eq(TypeEq::NEW);
190    /// assert!(matches!(eq.eq(), Some(TypeEq::<u8, u8>{..})));
191    /// 
192    /// let ne = TypeCmp::Ne(type_ne!(u8, i8));
193    /// assert!(matches!(ne.eq(), None::<TypeEq<u8, i8>>));
194    /// ```
195    pub const fn eq(self) -> Option<TypeEq<L, R>> {
196        match self {
197            TypeCmp::Eq(te) => Some(te),
198            TypeCmp::Ne(_) => None,
199        }
200    }
201
202    /// Converts this `TypeCmp<L, R>` into an `Option<TypeNe<L, R>>`.
203    /// 
204    /// # Example
205    /// 
206    /// ```rust
207    /// use typewit::{TypeCmp, TypeEq, TypeNe, type_ne};
208    /// 
209    /// let eq: TypeCmp<u8, u8> = TypeCmp::Eq(TypeEq::NEW);
210    /// assert!(matches!(eq.ne(), None::<TypeNe<u8, u8>>));
211    /// 
212    /// let ne = TypeCmp::Ne(type_ne!(u8, i8));
213    /// assert!(matches!(ne.ne(), Some(TypeNe::<u8, i8>{..})));
214    /// ```
215    pub const fn ne(self) -> Option<TypeNe<L, R>> {
216        match self {
217            TypeCmp::Eq(_) => None,
218            TypeCmp::Ne(te) => Some(te),
219        }
220    }
221
222    /// Returns whether this `TypeCmp` is a `TypeCmp::Eq`.
223    /// 
224    /// # Example
225    /// 
226    /// ```rust
227    /// use typewit::{TypeCmp, TypeEq, TypeNe, type_ne};
228    /// 
229    /// const EQ: TypeCmp<u8, u8> = TypeEq::NEW.to_cmp();
230    /// assert_eq!(EQ.is_eq(), true);
231    /// 
232    /// const NE: TypeCmp<i8, u8> = type_ne!(i8, u8).to_cmp();
233    /// assert_eq!(NE.is_eq(), false);
234    /// ```
235    pub const fn is_eq(self) -> bool {
236        matches!(self, TypeCmp::Eq(_))
237    }
238
239    /// Returns whether this `TypeCmp` is a `TypeCmp::Ne`.
240    /// 
241    /// # Example
242    /// 
243    /// ```rust
244    /// use typewit::{TypeCmp, TypeEq, TypeNe, type_ne};
245    /// 
246    /// const EQ: TypeCmp<u8, u8> = TypeEq::NEW.to_cmp();
247    /// assert_eq!(EQ.is_ne(), false);
248    /// 
249    /// const NE: TypeCmp<i8, u8> = type_ne!(i8, u8).to_cmp();
250    /// assert_eq!(NE.is_ne(), true);
251    /// ```
252    pub const fn is_ne(self) -> bool {
253        matches!(self, TypeCmp::Ne(_))
254    }
255
256    /// Returns the contained `TypeEq`
257    /// 
258    /// # Panic
259    /// 
260    /// Panics if the contained value is a `TypeNe`.
261    /// 
262    /// # Example
263    /// 
264    /// ```rust
265    /// use typewit::{TypeCmp, TypeEq};
266    /// 
267    /// let eq: TypeCmp<u8, u8> = TypeCmp::Eq(TypeEq::NEW);
268    /// assert!(matches!(eq.unwrap_eq(), TypeEq::<u8, u8>{..}));
269    /// ```
270    #[track_caller]
271    pub const fn unwrap_eq(self) -> TypeEq<L, R> {
272        match self {
273            TypeCmp::Eq(te) => te,
274            TypeCmp::Ne(_) => panic!("called `TypeCmp::unwrap_eq` on a `TypeNe` value"),
275        }
276    }
277
278    /// Returns the contained `TypeEq`
279    /// 
280    /// # Panic
281    /// 
282    /// Panics if the contained value is a `TypeNe`, with `msg` as the panic message.
283    /// 
284    /// # Example
285    /// 
286    /// ```rust
287    /// use typewit::{TypeCmp, TypeEq};
288    /// 
289    /// let eq: TypeCmp<u8, u8> = TypeCmp::Eq(TypeEq::NEW);
290    /// assert!(matches!(eq.expect_eq("they're the same type!"), TypeEq::<u8, u8>{..}));
291    /// ```
292    #[track_caller]
293    pub const fn expect_eq(self, msg: &str) -> TypeEq<L, R> {
294        match self {
295            TypeCmp::Eq(te) => te,
296            TypeCmp::Ne(_) => panic!("{}", msg),
297        }
298    }
299
300    /// Returns the contained `TypeNe`
301    /// 
302    /// # Panic
303    /// 
304    /// Panics if the contained value is a `TypeEq`.
305    /// 
306    /// # Example
307    /// 
308    /// ```rust
309    /// use typewit::{TypeCmp, TypeNe, type_ne};
310    /// 
311    /// let ne = TypeCmp::Ne(type_ne!(u8, i8));
312    /// assert!(matches!(ne.unwrap_ne(), TypeNe::<u8, i8>{..}));
313    /// ```
314    #[track_caller]
315    pub const fn unwrap_ne(self) -> TypeNe<L, R> {
316        match self {
317            TypeCmp::Eq(_) => panic!("called `TypeCmp::unwrap_ne` on a `TypeEq` value"),
318            TypeCmp::Ne(te) => te,
319        }
320    }
321
322    /// Returns the contained `TypeNe`
323    /// 
324    /// # Panic
325    /// 
326    /// Panics if the contained value is a `TypeEq`, with `msg` as the panic message.
327    /// 
328    /// # Example
329    /// 
330    /// ```rust
331    /// use typewit::{TypeCmp, TypeNe, type_ne};
332    /// 
333    /// let ne = TypeCmp::Ne(type_ne!(u8, i8));
334    /// assert!(matches!(ne.expect_ne("but u8 isn't i8..."), TypeNe::<u8, i8>{..}));
335    /// ```
336    #[track_caller]
337    pub const fn expect_ne(self, msg: &str) -> TypeNe<L, R> {
338        match self {
339            TypeCmp::Eq(_) => panic!("{}", msg),
340            TypeCmp::Ne(te) => te,
341        }
342    }
343}
344
345#[cfg(feature = "rust_1_61")]
346macro_rules! alternative_docs {
347    ($func:expr) => {concat!(
348        "# Alternative\n",
349        "\n",
350        "[`methods::", $func,"`](crate::methods::", $func, ") \n",
351        "is an alternative to this function. \n",
352        "\n",
353        "This method always returns `TypeCmp`, \n",
354        "while [that function](crate::methods::", $func, ")\n",
355        "returns [`TypeNe`] when any argument is a `TypeNe`.\n",
356        "\n",
357        "# Returned variant\n",
358        "\n",
359        "This returns either [`TypeCmp::Eq`] or [`TypeCmp::Ne`]",
360        " depending on the arguments:\n",
361        "- if all arguments (including `self`)",
362        " are [`TypeEq`] or [`TypeCmp::Eq`], this returns [`TypeCmp::Eq`] \n",
363        "- if any argument (including `self`) ",
364        "is a [`TypeNe`] or [`TypeCmp::Ne`], this returns [`TypeCmp::Ne`] \n",
365    )};
366}
367
368#[cfg(feature = "rust_1_61")]
369#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_61")))]
370impl<L, R> TypeCmp<L, R> {
371    /// Combines this `TypeCmp<L, R>` with a [`BaseTypeWitness`] type to produce a
372    /// `TypeCmp<(L, A::L), (R, A::R)>`.
373    /// 
374    #[doc = alternative_docs!("zip2")]
375    /// 
376    /// # Example
377    /// 
378    /// ```rust
379    /// use typewit::{TypeCmp, TypeEq, TypeNe, type_ne};
380    /// 
381    /// 
382    /// const NE: TypeNe<u8, i8> = type_ne!(u8, i8);
383    /// const EQ: TypeEq<u16, u16> = TypeEq::NEW;
384    /// const TC_NE: TypeCmp<u32, u64> = TypeCmp::Ne(type_ne!(u32, u64));
385    /// const TC_EQ: TypeCmp<i64, i64> = TypeCmp::Eq(TypeEq::NEW);
386    /// 
387    /// assert!(matches!(
388    ///     TC_EQ.zip(NE),
389    ///     TypeCmp::<(i64, u8), (i64, i8)>::Ne(_),
390    /// ));
391    /// 
392    /// assert!(matches!(
393    ///     TC_EQ.zip(EQ),
394    ///     TypeCmp::<(i64, u16), (i64, u16)>::Eq(_),
395    /// ));
396    /// 
397    /// assert!(matches!(
398    ///     TC_EQ.zip(TC_EQ),
399    ///     TypeCmp::<(i64, i64), (i64, i64)>::Eq(_),
400    /// ));
401    /// 
402    /// assert!(matches!(
403    ///     TC_EQ.zip(TC_NE),
404    ///     TypeCmp::<(i64, u32), (i64, u64)>::Ne(_),
405    /// ));
406    /// ```
407    pub const fn zip<A>(self, other: A) -> TypeCmp<(L, A::L), (R, A::R)> 
408    where
409        A: BaseTypeWitness,
410    {
411        let other = MetaBaseTypeWit::to_cmp(A::WITNESS, other);
412
413        match (self, other) {
414            (TypeCmp::Eq(tel), TypeCmp::Eq(ter)) => {
415                TypeCmp::Eq(tel.zip(ter))
416            }
417            (TypeCmp::Ne(ne), _) => {
418                TypeCmp::Ne(SomeTypeArgIsNe::A(TypeEq::NEW).zip2(ne, other))
419            }
420            (_, TypeCmp::Ne(ne)) => {
421                TypeCmp::Ne(SomeTypeArgIsNe::B(TypeEq::NEW).zip2(self, ne))
422            }
423        }
424    }
425
426    /// Combines this `TypeCmp<L, R>` with two [`BaseTypeWitness`] types to produce a
427    /// `TypeCmp<(L, A::L, B::L), (R, A::R, B::R)>`.
428    /// 
429    #[doc = alternative_docs!("zip3")]
430    /// 
431    /// # Example
432    /// 
433    /// ```rust
434    /// use typewit::{TypeCmp, TypeEq, TypeNe, type_ne};
435    /// 
436    /// 
437    /// const NE: TypeNe<u8, i8> = type_ne!(u8, i8);
438    /// const EQ: TypeEq<u16, u16> = TypeEq::NEW;
439    /// const TC_NE: TypeCmp<u32, u64> = TypeCmp::Ne(type_ne!(u32, u64));
440    /// const TC_EQ: TypeCmp<i64, i64> = TypeCmp::Eq(TypeEq::NEW);
441    /// 
442    /// assert!(matches!(
443    ///     TC_EQ.zip3(EQ, NE),
444    ///     TypeCmp::<(i64, u16, u8), (i64, u16, i8)>::Ne(_),
445    /// ));
446    /// 
447    /// assert!(matches!(
448    ///     TC_EQ.zip3(EQ, TC_EQ),
449    ///     TypeCmp::<(i64, u16, i64), (i64, u16, i64)>::Eq(_),
450    /// ));
451    /// 
452    /// assert!(matches!(
453    ///     TC_EQ.zip3(NE, TC_NE),
454    ///     TypeCmp::<(i64, u8, u32), (i64, i8, u64)>::Ne(_),
455    /// ));
456    /// ```
457    pub const fn zip3<A, B>(self, arg0: A, arg1: B) -> TypeCmp<(L, A::L, B::L), (R, A::R, B::R)> 
458    where
459        A: BaseTypeWitness,
460        A::L: Sized,
461        A::R: Sized,
462        B: BaseTypeWitness,
463    {
464        let arg0 = MetaBaseTypeWit::to_cmp(A::WITNESS, arg0);
465        let arg1 = MetaBaseTypeWit::to_cmp(B::WITNESS, arg1);
466
467        match (self, arg0, arg1) {
468            (TypeCmp::Eq(te0), TypeCmp::Eq(te1), TypeCmp::Eq(te2)) => {
469                TypeCmp::Eq(te0.zip3(te1, te2))
470            }
471            (TypeCmp::Ne(ne), _, _) => {
472                TypeCmp::Ne(SomeTypeArgIsNe::A(TypeEq::NEW).zip3(ne, arg0, arg1))
473            }
474            (_, TypeCmp::Ne(ne), _) => {
475                TypeCmp::Ne(SomeTypeArgIsNe::B(TypeEq::NEW).zip3(self, ne, arg1))
476            }
477            (_, _, TypeCmp::Ne(ne)) => {
478                TypeCmp::Ne(SomeTypeArgIsNe::C(TypeEq::NEW).zip3(self, arg0, ne))
479            }
480        }
481    }
482
483    /// Combines this `TypeCmp<L, R>` with three [`BaseTypeWitness`] types to produce a
484    /// `TypeCmp<(L, A::L, B::L, C::L), (R, A::R, B::R, C::R)>`.
485    ///
486    #[doc = alternative_docs!("zip4")]
487    ///
488    /// 
489    /// # Example
490    /// 
491    /// ```rust
492    /// use typewit::{TypeCmp, TypeEq, TypeNe, type_ne};
493    /// 
494    /// 
495    /// const NE: TypeNe<u8, i8> = type_ne!(u8, i8);
496    /// const EQ: TypeEq<u16, u16> = TypeEq::NEW;
497    /// const TC_NE: TypeCmp<u32, u64> = TypeCmp::Ne(type_ne!(u32, u64));
498    /// const TC_EQ: TypeCmp<i64, i64> = TypeCmp::Eq(TypeEq::NEW);
499    /// 
500    /// assert!(matches!(
501    ///     TC_EQ.zip4(EQ, NE, TC_NE),
502    ///     TypeCmp::<(i64, u16, u8, u32), (i64, u16, i8, u64)>::Ne(_),
503    /// ));
504    /// 
505    /// assert!(matches!(
506    ///     TC_EQ.zip4(EQ, TC_EQ, EQ),
507    ///     TypeCmp::<(i64, u16, i64, u16), (i64, u16, i64, u16)>::Eq(_),
508    /// ));
509    /// ```
510    pub const fn zip4<A, B, C>(
511        self, 
512        arg0: A, 
513        arg1: B, 
514        arg2: C,
515    ) -> TypeCmp<(L, A::L, B::L, C::L), (R, A::R, B::R, C::R)> 
516    where
517        A: BaseTypeWitness,
518        A::L: Sized,
519        A::R: Sized,
520        B: BaseTypeWitness,
521        B::L: Sized,
522        B::R: Sized,
523        C: BaseTypeWitness,
524    {
525        let arg0 = MetaBaseTypeWit::to_cmp(A::WITNESS, arg0);
526        let arg1 = MetaBaseTypeWit::to_cmp(B::WITNESS, arg1);
527        let arg2 = MetaBaseTypeWit::to_cmp(C::WITNESS, arg2);
528
529        match (self, arg0, arg1, arg2) {
530            (TypeCmp::Eq(te0), TypeCmp::Eq(te1), TypeCmp::Eq(te2), TypeCmp::Eq(te3)) => {
531                TypeCmp::Eq(te0.zip4(te1, te2, te3))
532            }
533            (TypeCmp::Ne(ne), _, _, _) => {
534                TypeCmp::Ne(SomeTypeArgIsNe::A(TypeEq::NEW).zip4(ne, arg0, arg1, arg2))
535            }
536            (_, TypeCmp::Ne(ne), _, _) => {
537                TypeCmp::Ne(SomeTypeArgIsNe::B(TypeEq::NEW).zip4(self, ne, arg1, arg2))
538            }
539            (_, _, TypeCmp::Ne(ne), _) => {
540                TypeCmp::Ne(SomeTypeArgIsNe::C(TypeEq::NEW).zip4(self, arg0, ne, arg2))
541            }
542            (_, _, _, TypeCmp::Ne(ne)) => {
543                TypeCmp::Ne(SomeTypeArgIsNe::D(TypeEq::NEW).zip4(self, arg0, arg1, ne))
544            }
545        }
546    }
547}
548
549
550// using this instead of `mod extra_type_cmp_methods;`
551// to document the impls in the submodule below the constructors.
552include!{"./type_cmp/extra_type_cmp_methods.rs"}
553
554
555impl<L: ?Sized, R: ?Sized> Copy for TypeCmp<L, R> {}
556
557impl<L: ?Sized, R: ?Sized> Clone for TypeCmp<L, R> {
558    fn clone(&self) -> Self {
559        *self
560    }
561}
562
563impl<L: ?Sized, R: ?Sized> Debug for TypeCmp<L, R> {
564    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
565        match self {
566            TypeCmp::Eq(x) => Debug::fmt(x, f),
567            TypeCmp::Ne(x) => Debug::fmt(x, f),
568        }
569    }
570}
571
572impl<L: ?Sized, R: ?Sized> PartialEq for TypeCmp<L, R> {
573    fn eq(&self, other: &Self) -> bool {
574        self.is_eq() == other.is_eq()
575    }
576}
577
578impl<L: ?Sized, R: ?Sized> PartialOrd for TypeCmp<L, R> {
579    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
580        self.is_eq().partial_cmp(&other.is_eq())
581    }
582}
583
584impl<L: ?Sized, R: ?Sized> Ord for TypeCmp<L, R> {
585    fn cmp(&self, other: &Self) -> Ordering {
586        self.is_eq().cmp(&other.is_eq())
587    }
588}
589
590impl<L: ?Sized, R: ?Sized> Eq for TypeCmp<L, R> {}
591
592impl<L: ?Sized, R: ?Sized> Hash for TypeCmp<L, R> {
593    fn hash<H>(&self, state: &mut H)
594    where H: Hasher
595    {
596        match self {
597            TypeCmp::Eq(x) => Hash::hash(x, state),
598            TypeCmp::Ne(x) => Hash::hash(x, state),
599        }
600    }
601}
602
603
604
605
606
607
608
609