typewit/
type_ne_.rs

1use core::{
2    any::{Any, TypeId},
3    cmp::{Ordering, Eq, Ord, PartialEq, PartialOrd},
4    hash::{Hash, Hasher},
5    fmt::{self, Debug},
6};
7
8use crate::TypeEq;
9
10#[cfg(feature = "rust_1_61")]
11use crate::{BaseTypeWitness, SomeTypeArgIsNe};
12
13
14/// Marker type, for constructing `TypeNe` in [`TypeNe::with_fn`] constructor.
15pub enum LeftArg {}
16
17/// Marker type, for constructing `TypeNe` in [`TypeNe::with_fn`] constructor.
18pub enum RightArg {}
19
20
21
22pub use self::type_ne_::TypeNe;
23
24mod type_ne_ {
25    use core::marker::PhantomData;
26
27    /// Value-level proof that `L` is a different type to `R`
28    /// 
29    /// The opposite of [`TypeEq`](crate::TypeEq).
30    /// 
31    /// # Example
32    /// 
33    /// ```rust
34    /// use typewit::{const_marker::Usize, TypeNe};
35    /// 
36    /// assert_eq!(
37    ///     array_ref_chunks(&[3, 5, 8, 13, 21, 34, 55], AssertNotZero::V), 
38    ///     Chunks {chunks: vec![&[3, 5, 8], &[13, 21, 34]], tail: &[55]}
39    /// );
40    /// 
41    /// 
42    /// fn array_ref_chunks<T, const LEN: usize>(
43    ///     slice: &[T], 
44    ///     _not_zero: TypeNe<Usize<LEN>, Usize<0>>,
45    /// ) -> Chunks<'_, T, LEN> {
46    ///     let mut chunks = slice.chunks_exact(LEN);
47    /// 
48    ///     Chunks {
49    ///         chunks: chunks.by_ref().map(|c| <&[T; LEN]>::try_from(c).unwrap()).collect(),
50    ///         tail: chunks.remainder(),
51    ///     }
52    /// }
53    /// 
54    /// #[derive(Debug, PartialEq, Eq)]
55    /// struct Chunks<'a, T, const LEN: usize> {
56    ///     chunks: Vec<&'a [T; LEN]>,
57    ///     tail: &'a [T],
58    /// }
59    /// 
60    /// struct AssertNotZero<const N: usize>;
61    /// 
62    /// impl<const N: usize> AssertNotZero<N> {
63    ///     const V: TypeNe<Usize<N>, Usize<0>> = Usize::<N>.equals(Usize::<0>).unwrap_ne();
64    /// }
65    /// 
66    /// ```
67    /// 
68    /// If you attempt to pass `0` as the length of the array chunks,
69    /// you'll get this compile-time error:
70    /// ```text
71    /// error[E0080]: evaluation of `main::_doctest_main_src_type_ne_rs_41_0::AssertNotZero::<0>::V` failed
72    ///   --> src/type_ne.rs:71:43
73    ///    |
74    /// 33 |     const V: TypeNe<Usize<N>, Usize<0>> = Usize::<N>.equals(Usize::<0>).unwrap_ne();
75    ///    |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'called `TypeCmp::unwrap_ne` on a `TypeEq` value', src/type_ne.rs:33:73
76    /// 
77    /// error[E0080]: erroneous constant used
78    ///  --> src/type_ne.rs:45:50
79    ///   |
80    /// 7 |     array_ref_chunks(&[3, 5, 8, 13, 21, 34, 55], AssertNotZero::<0>::V), 
81    ///   |                                                  ^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
82    /// 
83    /// ```
84    pub struct TypeNe<L: ?Sized, R: ?Sized>(PhantomData<TypeNeHelper<L, R>>);
85
86    // Declared to work around this error in old Rust versions:
87    // > error[E0658]: function pointers cannot appear in constant functions
88    struct TypeNeHelper<L: ?Sized, R: ?Sized>(
89        #[allow(dead_code)]
90        fn(PhantomData<L>) -> PhantomData<L>,
91        #[allow(dead_code)]
92        fn(PhantomData<R>) -> PhantomData<R>,
93    );
94
95    impl<L: ?Sized, R: ?Sized> TypeNe<L, R> {
96        /// Constructs a `TypeNe<L, R>`.
97        ///
98        /// # Safety
99        ///
100        /// You must ensure that `L != R`.
101        ///
102        #[inline(always)]
103        pub const unsafe fn new_unchecked() -> TypeNe<L, R> {
104            TypeNe(PhantomData)
105        }
106    }
107
108
109}
110
111impl TypeNe<(), ()> {
112    /// Constructs a `TypeNe` by mapping from a 
113    /// `TypeNe<`[`LeftArg`]`, `[`RightArg`]`>` 
114    /// with an [injective type-level function](crate::InjTypeFn).
115    /// 
116    /// # Alternative
117    /// 
118    /// The [`type_ne`](macro@crate::type_ne) macro can be used as syntactic sugar 
119    /// for calling this constructor with a one-off type-level function.
120    /// 
121    /// # Example
122    /// 
123    /// ```rust
124    /// use typewit::type_ne::{TypeNe, LeftArg, RightArg};
125    /// 
126    /// const NE: TypeNe<Option<String>, Vec<u16>> = TypeNe::with_fn(MakeNe::NEW);
127    /// 
128    /// typewit::inj_type_fn! {
129    ///     struct MakeNe<T, U>;
130    /// 
131    ///     impl LeftArg => Option<T>;
132    ///     impl RightArg => Vec<U>;
133    /// }
134    /// ```
135    pub const fn with_fn<F>(
136        _func: F,
137    ) -> TypeNe<CallInjFn<InvokeAlias<F>, LeftArg>, CallInjFn<InvokeAlias<F>, RightArg>>
138    where
139        InvokeAlias<F>: InjTypeFn<LeftArg> + InjTypeFn<RightArg>
140    {
141        core::mem::forget(_func);
142
143        // SAFETY: LeftArg isn't RightArg, dummy.
144        let this: TypeNe<LeftArg, RightArg> = unsafe { TypeNe::new_unchecked() };
145
146        projected_type_cmp!{this, LeftArg, RightArg, InvokeAlias<F>}
147    }
148}
149
150
151impl<L: ?Sized, R: ?Sized> TypeNe<L, R> {
152    /// Constructs `TypeNe<L, R>` if `L != R`, otherwise returns None.
153    /// 
154    /// # Example
155    /// 
156    /// ```rust
157    /// use typewit::TypeNe;
158    /// 
159    /// 
160    /// let _ne: TypeNe<u8, i8> = TypeNe::with_any().unwrap();
161    /// 
162    /// assert!(TypeNe::<u8, u8>::with_any().is_none());
163    /// 
164    /// ```
165    #[deprecated = concat!(
166        "fallout of `https://github.com/rust-lang/rust/issues/97156`,",
167        "`TypeId::of::<L>() != TypeId::of::<R>()` does not imply `L != R`"
168    )]
169    pub fn with_any() -> Option<Self>
170    where
171        L: Sized + Any,
172        R: Sized + Any,
173    {
174        if TypeId::of::<L>() != TypeId::of::<R>() {
175            // SAFETY: unsound for the deprecated reason
176            unsafe { Some(TypeNe::new_unchecked()) }
177        } else {
178            None
179        }
180    }
181
182    /// Converts this `TypeNe` into a [`TypeCmp`](crate::TypeCmp)
183    /// 
184    /// # Example
185    /// 
186    /// ```rust
187    /// use typewit::{TypeCmp, TypeNe, type_ne};
188    /// 
189    /// const NE: TypeNe<u8, i8> = type_ne!(u8, i8);
190    /// const TC: TypeCmp<u8, i8> = NE.to_cmp();
191    /// 
192    /// assert!(matches!(TC, TypeCmp::Ne(_)));
193    /// ```
194    #[inline(always)]
195    pub const fn to_cmp(self) -> crate::TypeCmp<L, R> {
196        crate::TypeCmp::Ne(self)
197    }
198
199    /// Swaps the type arguments of this `TypeNe`
200    /// 
201    /// # Example
202    /// 
203    /// ```rust
204    /// use typewit::{TypeNe, type_ne};
205    /// 
206    /// const NE: TypeNe<u8, i8> = type_ne!(u8, i8);
207    /// 
208    /// const N3: TypeNe<i8, u8> = NE.flip();
209    /// 
210    /// ```
211    pub const fn flip(self: TypeNe<L, R>) -> TypeNe<R, L> {
212        // SAFETY: type inequality is commutative
213        unsafe { TypeNe::<R, L>::new_unchecked() }
214    }
215
216    /// Joins a proof of `L != R` with a proof of `J == L`,
217    /// creating a proof of `J != R`.
218    /// 
219    /// # Example
220    /// 
221    /// ```rust
222    /// use typewit::{TypeEq, TypeNe, type_ne};
223    /// 
224    /// const NE: TypeNe<str, [u8]> = type_ne!(str, [u8]);
225    /// 
226    /// const fn foo<A: ?Sized>(eq: TypeEq<A, str>) {
227    ///     let _ne: TypeNe<A, [u8]> = NE.join_left(eq);
228    /// }
229    /// ```
230    pub const fn join_left<J: ?Sized>(self: TypeNe<L, R>, _eq: TypeEq<J, L>) -> TypeNe<J, R> {
231        // SAFETY: (L != R, J == L) implies J != R
232        unsafe { TypeNe::<J, R>::new_unchecked() }
233    }
234
235    /// Joins a proof of `L != R` with a proof of `R == J`,
236    /// creating a proof of `L != J`.
237    /// 
238    /// # Example
239    /// 
240    /// ```rust
241    /// use typewit::{TypeEq, TypeNe, type_ne};
242    /// 
243    /// const NE: TypeNe<String, Vec<u8>> = type_ne!(String, Vec<u8>);
244    /// 
245    /// const fn foo<A>(eq: TypeEq<Vec<u8>, A>) {
246    ///     let _ne: TypeNe<String, A> = NE.join_right(eq);
247    /// }
248    /// ```
249    pub const fn join_right<J: ?Sized>(self: TypeNe<L, R>, _eq: TypeEq<R, J>) -> TypeNe<L, J> {
250        // SAFETY: (L != R, R == J) implies L != J
251        unsafe { TypeNe::<L, J>::new_unchecked() }
252    }
253}
254
255#[cfg(feature = "rust_1_61")]
256#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_61")))]
257impl<L, R> TypeNe<L, R> {
258    /// Combines this `TypeNe<L, R>` with an 
259    /// [`A: BaseTypeWitness`](BaseTypeWitness) to produce a
260    /// `TypeNe<(L, A::L), (R, A::R)>`.
261    /// 
262    /// # Example
263    /// 
264    /// ```rust
265    /// use typewit::{TypeCmp, TypeEq, TypeNe, type_ne};
266    /// 
267    /// const NE: TypeNe<u8, i8> = type_ne!(u8, i8);
268    /// const EQ: TypeEq<u16, u16> = TypeEq::NEW;
269    /// const TC: TypeCmp<u32, u64> = TypeCmp::Ne(type_ne!(u32, u64));
270    /// 
271    /// let _: TypeNe<(u8, i8), (i8, u8)> = NE.zip(NE.flip());
272    /// let _: TypeNe<(u8, u16), (i8, u16)> = NE.zip(EQ);
273    /// let _: TypeNe<(u8, u32), (i8, u64)> = NE.zip(TC);
274    /// 
275    /// ```
276    pub const fn zip<A>(
277        self: TypeNe<L, R>,
278        other: A,
279    ) -> TypeNe<(L, A::L), (R, A::R)> 
280    where
281        A: BaseTypeWitness,
282    {
283        SomeTypeArgIsNe::A(TypeEq::NEW).zip2(self, other)
284    }
285
286    /// Combines this `TypeNe<L, R>` with 
287    /// two [`BaseTypeWitness`](BaseTypeWitness)es to produce a
288    /// `TypeNe<(L, A::L, B::L), (R, A::R, B::R)>`.
289    /// 
290    /// # Example
291    /// 
292    /// ```rust
293    /// use typewit::{TypeCmp, TypeEq, TypeNe, type_ne};
294    /// 
295    /// const NE: TypeNe<u8, i8> = type_ne!(u8, i8);
296    /// const EQ: TypeEq<u16, u16> = TypeEq::NEW;
297    /// const TC: TypeCmp<u32, u64> = TypeCmp::Ne(type_ne!(u32, u64));
298    /// 
299    /// let _: TypeNe<(u8, i8, u8), (i8, u8, i8)> = NE.zip3(NE.flip(), NE);
300    /// let _: TypeNe<(u8, u16, u16), (i8, u16, u16)> = NE.zip3(EQ, EQ.flip());
301    /// let _: TypeNe<(u8, u32, u64), (i8, u64, u32)> = NE.zip3(TC, TC.flip());
302    /// 
303    /// ```
304    pub const fn zip3<A, B>(
305        self: TypeNe<L, R>,
306        other1: A,
307        other2: B,
308    ) -> TypeNe<(L, A::L, B::L), (R, A::R, B::R)> 
309    where
310        A: BaseTypeWitness,
311        B: BaseTypeWitness,
312        A::L: Sized,
313        A::R: Sized,
314    {
315        SomeTypeArgIsNe::A(TypeEq::NEW).zip3(self, other1, other2)
316    }
317
318    /// Combines this `TypeNe<L, R>` with 
319    /// three [`BaseTypeWitness`](BaseTypeWitness)es to produce a
320    /// `TypeNe<(L, A::L, B::L, C::L), (R, A::R, B::R, C::R)> `.
321    /// 
322    /// # Example
323    /// 
324    /// ```rust
325    /// use typewit::{TypeCmp, TypeEq, TypeNe, type_ne};
326    /// 
327    /// const NE: TypeNe<u8, i8> = type_ne!(u8, i8);
328    /// const EQ: TypeEq<u16, u16> = TypeEq::NEW;
329    /// const TC: TypeCmp<u32, u64> = TypeCmp::Ne(type_ne!(u32, u64));
330    /// 
331    /// let _: TypeNe<(u8, i8, u8, i8), (i8, u8, i8, u8)> = NE.zip4(NE.flip(), NE, NE.flip());
332    /// let _: TypeNe<(u8, u16, u16, u16), (i8, u16, u16, u16)> = NE.zip4(EQ, EQ.flip(), EQ);
333    /// let _: TypeNe<(u8, u32, u64, u32), (i8, u64, u32, u64)> = NE.zip4(TC, TC.flip(), TC);
334    /// 
335    /// ```
336    pub const fn zip4<A, B, C>(
337        self: TypeNe<L, R>,
338        other1: A,
339        other2: B,
340        other3: C,
341    ) -> TypeNe<(L, A::L, B::L, C::L), (R, A::R, B::R, C::R)> 
342    where
343        A: BaseTypeWitness,
344        B: BaseTypeWitness,
345        C: BaseTypeWitness,
346        A::L: Sized,
347        A::R: Sized,
348        B::L: Sized,
349        B::R: Sized,
350    {
351        SomeTypeArgIsNe::A(TypeEq::NEW).zip4(self, other1, other2, other3)
352    }
353}
354
355
356
357// using this instead of `mod extra_type_ne_methods;`
358// to document the impls in the submodule below the constructors.
359include!{"./type_ne/extra_type_ne_methods.rs"}
360
361
362
363impl<L: ?Sized, R: ?Sized> Copy for TypeNe<L, R> {}
364
365impl<L: ?Sized, R: ?Sized> Clone for TypeNe<L, R> {
366    fn clone(&self) -> Self {
367        *self
368    }
369}
370
371impl<L: ?Sized, R: ?Sized> Debug for TypeNe<L, R> {
372    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
373        f.write_str("TypeNe")
374    }
375}
376
377impl<L: ?Sized, R: ?Sized> PartialEq for TypeNe<L, R> {
378    fn eq(&self, _: &Self) -> bool {
379        true
380    }
381}
382
383impl<L: ?Sized, R: ?Sized> PartialOrd for TypeNe<L, R> {
384    fn partial_cmp(&self, _: &Self) -> Option<Ordering> {
385        Some(Ordering::Equal)
386    }
387}
388
389impl<L: ?Sized, R: ?Sized> Ord for TypeNe<L, R> {
390    fn cmp(&self, _: &Self) -> Ordering {
391        Ordering::Equal
392    }
393}
394
395impl<L: ?Sized, R: ?Sized> Eq for TypeNe<L, R> {}
396
397impl<L: ?Sized, R: ?Sized> Hash for TypeNe<L, R> {
398    fn hash<H>(&self, _state: &mut H)
399    where H: Hasher
400    {}
401}
402
403
404