typewit/
lib.rs

1#![allow(clippy::needless_doctest_main)]
2//! This crate provides abstractions for creating
3//! [type witnesses](#what-are-type-witnesses).
4//! 
5//! The inciting motivation for this crate is emulating trait polymorphism in `const fn`
6//! (as of 2025-07-20, it's not possible to call trait methods in const contexts on stable).
7//! 
8//! # What are type witnesses
9//! 
10//! Type witnesses are values that prove the equality of a type parameter to a
11//! fixed set of possible types.
12//! 
13//! The simplest type witness is [`TypeEq<L, R>`][`TypeEq`],
14//! which only proves equality of its `L` and `R` type parameters,
15//! and can be used to coerce between them.
16//! 
17//! Most type witnesses are enums with [`TypeEq`] fields,
18//! which can coerce between a type parameter and as many types as there are variants.
19//! 
20//! # Examples
21//! 
22//! <span id="example0"></span>
23//! 
24//! ### Polymorphic function
25//! 
26//! This demonstrates how one can write a polymorphic `const fn`
27//! (as of 2025-07-20, trait methods can't be called in const fns on stable)
28//! 
29//! (this example requires Rust 1.61.0, since it uses trait bounds in const)
30#![cfg_attr(not(feature = "rust_1_61"), doc = "```ignore")]
31#![cfg_attr(feature = "rust_1_61", doc = "```rust")]
32//! use typewit::{HasTypeWitness, TypeEq};
33//! 
34//! const VALS: [&str; 6] = [
35//!     message(0),
36//!     message(1),
37//!     message(2),
38//!     message(3),
39//!     message("hi"),
40//!     message("foo"),
41//! ];
42//! assert_eq!(VALS, ["A", "B", "C", "A", "hi", "foo"]);
43//! 
44//! 
45//! // A "method" of the `Message` trait (declared below)
46//! const fn message<'a, T: Message<'a>>(val: T) -> &'a str {
47//!     match HasTypeWitness::WITNESS {
48//!         MessageWitness::Usize(te) => {
49//!             // `te` (a `TypeEq<T, usize>`) allows coercing between `T` and `usize`,
50//!             // because `TypeEq` is a value-level proof that both types are the same.
51//!             let index: usize = te.to_right(val);
52//!             ["A", "B", "C"][index % 3]
53//!         }
54//!         MessageWitness::Str(te) => {
55//!             // `te` is a `TypeEq<T, &'a str>`
56//!             te.to_right(val)
57//!         }
58//!     }
59//! }
60//! 
61//! // The trait that we use to emulate polymorphic dispatch,
62//! // the limitation is that it can only emulate it for a limited set of types known
63//! // to the crate that defines the trait, in this case that's `usize` and `&str`.
64//! trait Message<'a>: HasTypeWitness<MessageWitness<'a, Self>> { }
65//! 
66//! // replacing these impls with a blanket impl leads to worse compilation errors
67//! impl<'a> Message<'a> for usize {}
68//! impl<'a> Message<'a> for &'a str {}
69//! 
70//! // This macro declares `enum MessageWitness<'a, __Wit>`, a type witness enum,
71//! // where each variant requires and then guarantees `__Wit` to be a particular type.
72//! // (the `__Wit` type parameter is implicitly added after all generics)
73//! typewit::simple_type_witness! {
74//!     enum MessageWitness<'a> {
75//!         // This variant requires `__Wit == usize`
76//!         Usize = usize,
77//!    
78//!         // This variant requires `__Wit == &'a str`
79//!         Str = &'a str,
80//!     }
81//! }
82//! ```
83//! 
84//! <span id="example-uses-type-fn"></span>
85//! ### Indexing polymorphism
86//! 
87//! This function demonstrates const fn polymorphism
88//! and projecting [`TypeEq`] by implementing [`TypeFn`].
89//! 
90//! (this example requires Rust 1.71.0, because it uses `<[T]>::split_at` in a const context.
91#![cfg_attr(not(feature = "rust_stable"), doc = "```ignore")]
92#![cfg_attr(feature = "rust_stable", doc = "```rust")]
93//! use std::ops::Range;
94//! 
95//! use typewit::{HasTypeWitness, TypeEq};
96//! 
97//! fn main() {
98//!     let array = [3, 5, 8, 13, 21, 34, 55, 89];
99//! 
100//!     assert_eq!(index(&array, 0), &3);
101//!     assert_eq!(index(&array, 3), &13);
102//!     assert_eq!(index(&array, 0..4), [3, 5, 8, 13]);
103//!     assert_eq!(index(&array, 3..5), [13, 21]);
104//! }
105//! 
106//! const fn index<T, I>(slice: &[T], idx: I) -> &SliceIndexRet<I, T>
107//! where
108//!     I: SliceIndex<T>,
109//! {
110//!     // `I::WITNESS` is `<I as HasTypeWitness<IndexWitness<I>>>::WITNESS`,
111//!     match I::WITNESS {
112//!         IndexWitness::Usize(arg_te) => {
113//!             // `arg_te` (a `TypeEq<I, usize>`) allows coercing between `I` and `usize`,
114//!             // because `TypeEq` is a value-level proof that both types are the same.
115//!             let idx: usize = arg_te.to_right(idx);
116//! 
117//!             // using the `TypeFn` impl for `FnSliceIndexRet<T>` to 
118//!             // map `TypeEq<I, usize>` 
119//!             // to  `TypeEq<SliceIndexRet<I, T>, SliceIndexRet<usize, T>>`
120//!             arg_te.project::<FnSliceIndexRet<T>>()
121//!                 // converts`TypeEq<SliceIndexRet<I, T>, T>` 
122//!                 //      to `TypeEq<&SliceIndexRet<I, T>, &T>`
123//!                 .in_ref()
124//!                 .to_left(&slice[idx])
125//!         }
126//!         IndexWitness::Range(arg_te) => {
127//!             let range: Range<usize> = arg_te.to_right(idx);
128//!             let ret: &[T] = slice_range(slice, range);
129//!             arg_te.project::<FnSliceIndexRet<T>>().in_ref().to_left(ret)
130//!         }
131//!     }
132//! }
133//! 
134//! // This macro declares a type witness enum
135//! typewit::simple_type_witness! {
136//!     // Declares `enum IndexWitness<__Wit>` 
137//!     // (the `__Wit` type parameter is implicitly added after all generics)
138//!     enum IndexWitness {
139//!         // This variant requires `__Wit == usize`
140//!         Usize = usize,
141//!    
142//!         // This variant requires `__Wit == Range<usize>`
143//!         Range = Range<usize>,
144//!     }
145//! }
146//! 
147//! /// Trait for all types that can be used as slice indices
148//! /// 
149//! /// The `HasTypeWitness` supertrait allows getting a `IndexWitness<Self>`
150//! /// with its `WITNESS` associated constant.
151//! trait SliceIndex<T>: HasTypeWitness<IndexWitness<Self>> + Sized {
152//!     type Returns: ?Sized;
153//! }
154//! impl<T> SliceIndex<T> for usize {
155//!     type Returns = T;
156//! }
157//! impl<T> SliceIndex<T> for Range<usize> {
158//!     type Returns = [T];
159//! }
160//! 
161//! type SliceIndexRet<I, T> = <I as SliceIndex<T>>::Returns;
162//! 
163//! // Declares `struct FnSliceIndexRet<T>`
164//! // a type-level function (TypeFn implementor) from `I` to `SliceIndexRet<I, T>`
165//! typewit::type_fn! {
166//!     struct FnSliceIndexRet<T>;
167//!
168//!     impl<I: SliceIndex<T>> I => SliceIndexRet<I, T>
169//! }
170//! 
171//! const fn slice_range<T>(slice: &[T], range: Range<usize>) -> &[T] {
172//!     let suffix = slice.split_at(range.start).1;
173//!     suffix.split_at(range.end - range.start).0
174//! }
175//! 
176//! ```
177//! 
178//! When the wrong type is passed for the index,
179//! the compile-time error is the same as with normal generic functions:
180//! ```text
181//! error[E0277]: the trait bound `RangeFull: SliceIndex<{integer}>` is not satisfied
182//!   --> src/main.rs:43:30
183//!    |
184//! 13 |     assert_eq!(index(&array, ..), [13, 21]);
185//!    |                -----         ^^ the trait `SliceIndex<{integer}>` is not implemented for `RangeFull`
186//!    |                |
187//!    |                required by a bound introduced by this call
188//!    |
189//!    = help: the following other types implement trait `SliceIndex<T>`:
190//!              std::ops::Range<usize>
191//!              usize
192//! ```
193//! 
194//! ### Downcasting const generic type
195//! 
196//! This example demonstrates "downcasting" from a type with a const parameter to 
197//! a concrete instance of that type.
198//! 
199//! ```rust
200//! use typewit::{const_marker::Usize, TypeCmp, TypeEq};
201//! 
202//! assert_eq!(*mutate(&mut Arr([])), Arr([]));
203//! assert_eq!(*mutate(&mut Arr([1])), Arr([1]));
204//! assert_eq!(*mutate(&mut Arr([1, 2])), Arr([1, 2]));
205//! assert_eq!(*mutate(&mut Arr([1, 2, 3])), Arr([1, 3, 6])); // this is different!
206//! assert_eq!(*mutate(&mut Arr([1, 2, 3, 4])), Arr([1, 2, 3, 4])); 
207//! 
208//! #[derive(Debug, PartialEq)]
209//! struct Arr<const N: usize>([u8; N]);
210//! 
211//! fn mutate<const N: usize>(arr: &mut Arr<N>) -> &mut Arr<N> {
212//!     if let TypeCmp::Eq(te) =  Usize::<N>.equals(Usize::<3>) {
213//!         let tem = te // `te` is a `TypeEq<Usize<N>, Usize<3>>`
214//!             .project::<GArr>() // returns `TypeEq<Arr<N>, Arr<3>>`
215//!             .in_mut(); // returns `TypeEq<&mut Arr<N>, &mut Arr<3>>`
216//! 
217//!         // `tem.to_right(arr)` downcasts `arr` to `&mut Arr<3>`
218//!         tetra_sum(tem.to_right(arr));
219//!     }
220//! 
221//!     arr
222//! }
223//! 
224//! fn tetra_sum(arr: &mut Arr<3>) {
225//!     arr.0[1] += arr.0[0];
226//!     arr.0[2] += arr.0[1];
227//! }
228//! 
229//! // Declares `struct GArr`
230//! // a type-level function (TypeFn implementor) from `Usize<N>` to `Arr<N>`
231//! typewit::type_fn!{
232//!     struct GArr;
233//! 
234//!     impl<const N: usize> Usize<N> => Arr<N>
235//! }
236//! ```
237//! 
238//! ### Builder
239//! 
240//! Using a type witness to help encode a type-level enum,
241//! and to match on that type-level enum inside of a function.
242//! 
243//! The type-level enum is used to track the initialization of fields in a builder.
244//! 
245//! This example requires Rust 1.65.0, because it uses Generic Associated Types.
246#![cfg_attr(not(feature = "rust_1_65"), doc = "```ignore")]
247#![cfg_attr(feature = "rust_1_65", doc = "```rust")]
248//! use typewit::HasTypeWitness;
249//! 
250//! fn main() {
251//!     // all default fields
252//!     assert_eq!(
253//!         StructBuilder::new().build(), 
254//!         Struct{foo: "default value".into(), bar: vec![3, 5, 8]},
255//!     );
256//! 
257//!     // defaulted bar field
258//!     assert_eq!(
259//!         StructBuilder::new().foo("hello").build(), 
260//!         Struct{foo: "hello".into(), bar: vec![3, 5, 8]},
261//!     );
262//! 
263//!     // defaulted foo field
264//!     assert_eq!(
265//!         StructBuilder::new().bar([13, 21, 34]).build(), 
266//!         Struct{foo: "default value".into(), bar: vec![13, 21, 34]},
267//!     );
268//! 
269//!     // all initialized fields
270//!     assert_eq!(
271//!         StructBuilder::new().foo("world").bar([55, 89]).build(), 
272//!         Struct{foo: "world".into(), bar: vec![55, 89]},
273//!     );
274//! }
275//! 
276//! 
277//! #[derive(Debug, PartialEq, Eq)]
278//! struct Struct {
279//!     foo: String,
280//!     bar: Vec<u32>,
281//! }
282//! 
283//! struct StructBuilder<FooInit: InitState, BarInit: InitState> {
284//!     // If `FooInit` is `Uninit`, then this field is a `()`
285//!     // If `FooInit` is `Init`, then this field is a `String`
286//!     foo: BuilderField<FooInit, String>,
287//!
288//!     // If `BarInit` is `Uninit`, then this field is a `()`
289//!     // If `BarInit` is `Init`, then this field is a `Vec<u32>`
290//!     bar: BuilderField<BarInit, Vec<u32>>,
291//! }
292//! 
293//! impl StructBuilder<Uninit, Uninit> {
294//!     pub const fn new() -> Self {
295//!         Self {
296//!             foo: (),
297//!             bar: (),
298//!         }
299//!     }
300//! }
301//! 
302//! impl<FooInit: InitState, BarInit: InitState> StructBuilder<FooInit, BarInit> {
303//!     /// Sets the `foo` field
304//!     pub fn foo(self, foo: impl Into<String>) -> StructBuilder<Init, BarInit> {
305//!         StructBuilder {
306//!             foo: foo.into(),
307//!             bar: self.bar,
308//!         }
309//!     }
310//!
311//!     /// Sets the `bar` field
312//!     pub fn bar(self, bar: impl Into<Vec<u32>>) -> StructBuilder<FooInit, Init> {
313//!         StructBuilder {
314//!             foo: self.foo,
315//!             bar: bar.into(),
316//!         }
317//!     }
318//! 
319//!     /// Builds `Struct`, 
320//!     /// providing default values for fields that haven't been set.
321//!     pub fn build(self) -> Struct {
322//!         Struct {
323//!             foo: init_or_else::<FooInit, _, _>(self.foo, || "default value".to_string()),
324//!             bar: init_or_else::<BarInit, _, _>(self.bar, || vec![3, 5, 8]),
325//!         }
326//!     }
327//! }
328//! 
329//! // Emulates a type-level `enum InitState { Init, Uninit }`
330//! trait InitState: Sized + HasTypeWitness<InitWit<Self>> {
331//!     // How a builder represents an initialized/uninitialized field.
332//!     // If `Self` is `Uninit`, then this is `()`.
333//!     // If `Self` is `Init`, then this is `T`.
334//!     type BuilderField<T>;
335//! }
336//! 
337//! // If `I` is `Uninit`, then this evaluates to `()`
338//! // If `I` is `Init`, then this evaluates to `T`
339//! type BuilderField<I, T> = <I as InitState>::BuilderField::<T>;
340//! 
341//! /// Gets `T` out of `maybe_init` if it's actually initialized,
342//! /// otherwise returns `else_()`.
343//! fn init_or_else<I, T, F>(maybe_init: BuilderField<I, T>, else_: F) -> T
344//! where
345//!     I: InitState,
346//!     F: FnOnce() -> T
347//! {
348//!     typewit::type_fn! {
349//!         // Declares the `HelperFn` type-level function (TypeFn implementor)
350//!         // from `I` to `BuilderField<I, T>`
351//!         struct HelperFn<T>;
352//!         impl<I: InitState> I => BuilderField<I, T>
353//!     }
354//! 
355//!     // matching on the type-level `InitState` enum by using `InitWit`.
356//!     // `WITNESS` comes from the `HasTypeWitness` trait
357//!     match I::WITNESS {
358//!         // `te: TypeEq<FooInit, Init>`
359//!         InitWit::InitW(te) => {
360//!             te.map(HelperFn::NEW) //: TypeEq<BuilderField<I, T>, T>
361//!               .to_right(maybe_init)
362//!         }
363//!         InitWit::UninitW(_) => else_(),
364//!     }
365//! }
366//! 
367//! // Emulates a type-level `InitState::Init` variant.
368//! // Marks a field as initialized.
369//! enum Init {}
370//! 
371//! impl InitState for Init {
372//!     type BuilderField<T> = T;
373//! }
374//! 
375//! // Emulates a type-level `InitState::Uninit` variant.
376//! // Marks a field as uninitialized.
377//! enum Uninit {}
378//! 
379//! impl InitState for Uninit {
380//!     type BuilderField<T> = ();
381//! }
382//! 
383//! typewit::simple_type_witness! {
384//!     // Declares `enum InitWit<__Wit>`, a type witness.
385//!     // (the `__Wit` type parameter is implicitly added after all generics)
386//!     enum InitWit {
387//!         // This variant requires `__Wit == Init`
388//!         InitW = Init,
389//!         // This variant requires `__Wit == Uninit`
390//!         UninitW = Uninit,
391//!     }
392//! }
393//! ```
394//! 
395//! ### Generic Const Expressions
396//! 
397//! This example uses [`Usize`] to coerce an arrays whose length is generic to 
398//! another generic, but equal, length.
399//! 
400//! This example requires the `"generic_const_exprs"` crate feature because it uses the
401//! currently-unstable [`generic_const_exprs`] language feature.
402#![cfg_attr(not(feature = "generic_const_exprs"), doc = "```ignore")]
403#![cfg_attr(feature = "generic_const_exprs", doc = "```rust")]
404//! #![feature(generic_const_exprs)]
405//! 
406//! use typewit::{const_marker::Usize, TypeCmp, TypeEq};
407//! 
408//! 
409//! let mut arrays = Arrays::<1, 3> { a: [3, 5, 8], b: [13, 21, 34] };
410//! 
411//! arrays.swap_inner();
412//! 
413//! assert_eq!(arrays.a, [13, 21, 34]);
414//! assert_eq!(arrays.b, [3, 5, 8]);
415//! 
416//! 
417//! struct Arrays<const A: usize, const B: usize> 
418//! where
419//!     [u8; A * B]:, 
420//!     [u8; B * A]:,
421//! {
422//!     a: [u8; A * B],
423//!     b: [u8; B * A],
424//! }
425//! 
426//! impl<const A: usize, const B: usize> Arrays<A, B> 
427//! where
428//!     [u8; A * B]:, 
429//!     [u8; B * A]:,
430//! {
431//!     // Swaps the two array fields
432//!     const fn swap_inner(&mut self) {
433//!         let a = TypeEq::new::<u8>() // : TypeEq<u8, u8>
434//!             .in_array(commutative_proof::<A, B>()) // : TypeEq<[u8; A * B], [u8; B * A]>
435//!             .in_mut() // : TypeEq<&mut [u8; A * B], &mut [u8; B * A]>
436//!             .to_right(
437//!                 &mut self.a // : &mut [u8; A * B] 
438//!             ); // : &mut [u8; B * A] 
439//!         
440//!         core::mem::swap(a, &mut self.b);
441//!     }
442//! }
443//! 
444//! const fn commutative_proof<const A: usize, const B: usize>(
445//! ) -> TypeEq<Usize<{A * B}>, Usize<{B * A}>>
446//! {
447//!     // panic-safety: A * B == B * A always holds, so this `unwrap_eq` can never panic
448//!     Usize::<{A * B}>.equals(Usize::<{B * A}>).unwrap_eq()
449//! }
450//! 
451//! ```
452//! 
453//! If you tried to swap the fields directly, you'd get this error:
454//! ```text
455//! error[E0308]: mismatched types
456//!   --> src/lib.rs:437:38
457//!    |
458//! 42 |         core::mem::swap(&mut self.a, &mut self.b);
459//!    |                                      ^^^^^^^^^^^ expected `A * B`, found `B * A`
460//!    |
461//!    = note: expected constant `A * B`
462//!               found constant `B * A`
463//! ```
464//! 
465//! 
466//! # Cargo features
467//! 
468//! These are the features of this crate.
469//! 
470//! ### Default-features
471//! 
472//! These features are enabled by default:
473//! 
474//! - `"proc_macros"`: uses proc macros to improve compile-errors involving 
475//! macro-generated impls.
476//! 
477//! ### Rust-versions and standard crates
478//! 
479//! These features enable items that have a minimum Rust version:
480//! 
481//! - `"rust_stable"`: enables all the `"rust_1_*"` features.
482//! 
483//! - `"rust_1_83"`: turns functions that take mutable references into `const fn`s,
484//! enables [`const_marker`] items for comparing [`ConstMarker`]s,
485//! and enables the `"rust_1_65"` feature.
486//! 
487//! - `"rust_1_65"`: enables the [`type_constructors`] module,
488//! the [`methods`] module,
489//! and the `"rust_1_61"` feature.
490//! 
491//! - `"rust_1_61"`: enables [`MetaBaseTypeWit`],
492//! [`BaseTypeWitness`],
493//! and the `{TypeCmp, TypeNe}::{zip*, in_array}` methods.
494//!
495//! These features enable items that require a non-`core` standard crate:
496//! 
497//! - `"alloc"`: enable items that use anything from the standard `alloc` crate.
498//! 
499//! ### Nightly features
500//! 
501//! These features require the nightly Rust compiler:
502//! 
503//! - `"adt_const_marker"`:
504//! enables the `"rust_stable"` crate feature,
505//! and marker types in the [`const_marker`] module that have
506//! non-primitive `const` parameters.
507//! 
508//! - `"generic_const_exprs"`:
509//! enables the `"rust_stable"` crate feature,
510//! and doc examples that use the [`generic_const_exprs`] unstable language feature.
511//! 
512//! # No-std support
513//! 
514//! `typewit` is `#![no_std]`, it can be used anywhere Rust can be used.
515//! 
516//! You need to enable the `"alloc"` feature to enable items that use anything 
517//! from the standard `alloc` crate.
518//! 
519//! # Minimum Supported Rust Version
520//! 
521//! `typewit` supports Rust 1.57.0.
522//! 
523//! Features that require newer versions of Rust, or the nightly compiler,
524//! need to be explicitly enabled with crate features.
525//! 
526//! 
527//! 
528//! [`TypeCmp`]: crate::TypeCmp
529//! [`TypeEq`]: crate::TypeEq
530//! [`TypeNe`]: crate::TypeNe
531//! [`TypeFn`]: crate::type_fn::TypeFn
532//! [`const_marker`]: crate::const_marker
533//! [`type_constructors`]: crate::type_constructors
534//! [`methods`]: crate::methods
535//! [`MetaBaseTypeWit`]: crate::MetaBaseTypeWit
536//! [`BaseTypeWitness`]:  crate::BaseTypeWitness
537//! [`Usize`]: crate::const_marker::Usize
538//! [`typewit::const_marker`]: crate::const_marker
539//! [`ConstMarker`]: crate::const_marker::ConstMarker
540//! [`generic_const_exprs`]: https://doc.rust-lang.org/unstable-book/language-features/generic-const-exprs.html
541#![no_std]
542#![cfg_attr(feature = "adt_const_marker", feature(adt_const_params))]
543#![cfg_attr(feature = "adt_const_marker", feature(unsized_const_params))]
544#![cfg_attr(feature = "adt_const_marker", allow(incomplete_features))]
545#![cfg_attr(feature = "docsrs", feature(doc_cfg))]
546#![allow(clippy::type_complexity)]
547#![deny(missing_docs)]
548#![deny(clippy::missing_const_for_fn)]
549#![deny(unused_results)]
550
551#[cfg(feature = "alloc")]
552extern crate alloc;
553
554
555// Documentation for concepts not specific to any one item
556macro_rules! explain_type_witness {
557    () => ("\
558        A [type witness](crate#what-are-type-witnesses) is \
559        an enum whose variants only have [`TypeEq`](crate::TypeEq) fields.
560        Each variant requires the enum's type parameter to be a specific type.
561    ")
562}
563
564#[macro_use]
565pub mod type_fn;
566
567pub mod const_marker;
568
569#[cfg(feature = "adt_const_marker")]
570mod all_init_bytes;
571
572mod utils;
573mod macros;
574
575#[cfg(feature = "rust_1_61")]
576mod base_type_wit;
577
578#[cfg(feature = "rust_1_61")]
579pub use crate::base_type_wit::{BaseTypeWitness, MetaBaseTypeWit};
580
581
582#[cfg(feature = "rust_1_65")]
583#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_65")))]
584pub mod methods;
585
586
587#[cfg(feature = "rust_1_61")]
588pub(crate) mod some_type_arg_is_ne;
589
590#[cfg(feature = "rust_1_61")]
591pub(crate) use self::some_type_arg_is_ne::SomeTypeArgIsNe;
592
593
594mod type_cmp;
595mod type_eq;
596mod type_eq_ne_guts;
597mod type_identity;
598
599mod type_ne_;
600
601/// [`TypeNe`]-related items
602pub mod type_ne {
603    pub use crate::type_ne_::{LeftArg, RightArg};
604    
605    #[doc(no_inline)]
606    pub use crate::{TypeNe, type_ne};
607}
608
609
610mod type_witness_traits;
611
612#[cfg(feature = "rust_1_65")]
613pub mod type_constructors;
614
615
616#[doc(inline)]
617pub use crate::{
618    type_eq::*,
619    type_ne_::TypeNe,
620    type_witness_traits::*,
621    type_identity::Identity,
622};
623
624
625pub use crate::type_cmp::TypeCmp;
626
627#[doc(no_inline)]
628pub use crate::type_fn::{CallFn, CallInjFn, InjTypeFn, RevTypeFn, TypeFn, UncallFn};
629
630
631#[cfg(feature = "proc_macros")]
632#[doc(hidden)]
633pub use typewit_proc_macros::__impl_with_span;
634
635/// tests doc lints with `cargo doc --features="__test_doc_lints rust_stable"`
636#[cfg(all(feature = "__test_doc_lints"))]
637pub mod test_doc_lints;
638
639#[doc(hidden)]
640pub mod __ {
641    pub use core::{
642        clone::Clone,
643        cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering},
644        fmt::{Debug, Formatter, Result as FmtResult},
645        hash::{Hash, Hasher},
646        marker::{Copy, PhantomData},
647        mem::{ManuallyDrop, discriminant},
648        option::Option,
649        primitive::{bool, usize},
650        assert, compile_error, concat, stringify,
651    };
652
653    pub use crate::{
654        type_identity::Identity,
655        macros::{
656            generics_parsing::{
657                __parse_generic_args_with_defaults,
658                __parse_in_generics,
659                __parse_ty_bounds,
660                __parse_where_clause_for_item_inner,
661                __pg_cfg_expansion,
662                __pg_parsed_ty_bounds,
663            },
664            simple_type_witness_macro::__stw_parse_variants,
665        },
666    };
667
668}
669
670
671
672#[cfg(all(doctest, feature = "generic_const_exprs"))]
673#[doc = include_str!("../README.md")]
674pub struct ReadmeTest;