{"id":22290728,"url":"https://github.com/rodrimati1992/typewit","last_synced_at":"2025-07-28T23:31:49.001Z","repository":{"id":158929440,"uuid":"631675221","full_name":"rodrimati1992/typewit","owner":"rodrimati1992","description":"type-witness-based abstractions, used for emulating polymorphism in const fns","archived":false,"fork":false,"pushed_at":"2025-07-20T02:42:48.000Z","size":395,"stargazers_count":11,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-20T03:21:49.008Z","etag":null,"topics":["const","gadt","type-witness"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"zlib","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rodrimati1992.png","metadata":{"files":{"readme":"README.md","changelog":"Changelog.md","contributing":null,"funding":null,"license":"LICENSE-ZLIB.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-04-23T19:04:29.000Z","updated_at":"2025-07-20T02:42:53.000Z","dependencies_parsed_at":"2023-09-25T07:24:25.395Z","dependency_job_id":"b16eef75-e4bd-4bf2-83c4-6024bc06f2ba","html_url":"https://github.com/rodrimati1992/typewit","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/rodrimati1992/typewit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rodrimati1992%2Ftypewit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rodrimati1992%2Ftypewit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rodrimati1992%2Ftypewit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rodrimati1992%2Ftypewit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rodrimati1992","download_url":"https://codeload.github.com/rodrimati1992/typewit/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rodrimati1992%2Ftypewit/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267604302,"owners_count":24114521,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-28T02:00:09.689Z","response_time":68,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["const","gadt","type-witness"],"created_at":"2024-12-03T17:13:54.054Z","updated_at":"2025-07-28T23:31:48.993Z","avatar_url":"https://github.com/rodrimati1992.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Rust](https://github.com/rodrimati1992/typewit/workflows/Rust/badge.svg)](https://github.com/rodrimati1992/typewit/actions)\n[![crates-io](https://img.shields.io/crates/v/typewit.svg)](https://crates.io/crates/typewit)\n[![api-docs](https://docs.rs/typewit/badge.svg)](https://docs.rs/typewit/*)\n\n\nThis crate provides abstractions for creating\n[type witnesses](#what-are-type-witnesses).\n\nThe inciting motivation for this crate is emulating trait polymorphism in `const fn`\n(as of 2025-07-20, it's not possible to call trait methods in const contexts on stable).\n\n# What are type witnesses\n\nType witnesses are enums that allow coercing between a type parameter and a\nrange of possible types (one per variant).\n\nThe simplest type witness is [`TypeEq\u003cL, R\u003e`](crate::TypeEq),\nwhich only allows coercing between `L` and `R`.\n\nMost type witnesses are enums with [`TypeEq`] fields,\nwhich can coerce between a type parameter and as many types as there are variants.\n\n# Examples\n\n\u003cspan id=\"example0\"\u003e\u003c/span\u003e\n\n### Polymorphic function\n\nThis demonstrates how one can write a polymorphic `const fn`\n(as of 2025-07-20, trait methods can't be called in const fns on stable)\n\n(this example requires Rust 1.61.0, since it uses trait bounds in const)\n```rust\nuse typewit::{HasTypeWitness, TypeEq};\n\nconst VALS: [\u0026str; 6] = [\n    message(0),\n    message(1),\n    message(2),\n    message(3),\n    message(\"hi\"),\n    message(\"foo\"),\n];\nassert_eq!(VALS, [\"A\", \"B\", \"C\", \"A\", \"hi\", \"foo\"]);\n\n\n// A \"method\" of the `Message` trait (declared below)\nconst fn message\u003c'a, T: Message\u003c'a\u003e\u003e(val: T) -\u003e \u0026'a str {\n    match HasTypeWitness::WITNESS {\n        MessageWitness::Usize(te) =\u003e {\n            // `te` (a `TypeEq\u003cT, usize\u003e`) allows coercing between `T` and `usize`,\n            // because `TypeEq` is a value-level proof that both types are the same.\n            let index: usize = te.to_right(val);\n            [\"A\", \"B\", \"C\"][index % 3]\n        }\n        MessageWitness::Str(te) =\u003e {\n            // `te` is a `TypeEq\u003cT, \u0026'a str\u003e`\n            te.to_right(val)\n        }\n    }\n}\n\n// The trait that we use to emulate polymorphic dispatch,\n// the limitation is that it can only emulate it for a limited set of types known\n// to the crate that defines the trait, in this case that's `usize` and `\u0026str`.\ntrait Message\u003c'a\u003e: HasTypeWitness\u003cMessageWitness\u003c'a, Self\u003e\u003e { }\n\n// replacing these impls with a blanket impl leads to worse compilation errors\nimpl\u003c'a\u003e Message\u003c'a\u003e for usize {}\nimpl\u003c'a\u003e Message\u003c'a\u003e for \u0026'a str {}\n\n// This macro declares `enum MessageWitness\u003c'a, __Wit\u003e`, a type witness enum,\n// where each variant requires and then guarantees `__Wit` to be a particular type.\n// (the `__Wit` type parameter is implicitly added after all generics)\ntypewit::simple_type_witness! {\n    enum MessageWitness\u003c'a\u003e {\n        // This variant requires `__Wit == usize`\n        Usize = usize,\n   \n        // This variant requires `__Wit == \u0026'a str`\n        Str = \u0026'a str,\n    }\n}\n```\n\n\n\u003cspan id=\"example-uses-type-fn\"\u003e\u003c/span\u003e\n### Indexing polymorphism\n\nThis function demonstrates const fn polymorphism\nand projecting [`TypeEq`] by implementing [`TypeFn`].\n\n(this example requires Rust 1.71.0, because it uses `\u003c[T]\u003e::split_at` in a const context.\n```rust\nuse std::ops::Range;\n\nuse typewit::{HasTypeWitness, TypeEq};\n\nfn main() {\n    let array = [3, 5, 8, 13, 21, 34, 55, 89];\n\n    assert_eq!(index(\u0026array, 0), \u00263);\n    assert_eq!(index(\u0026array, 3), \u002613);\n    assert_eq!(index(\u0026array, 0..4), [3, 5, 8, 13]);\n    assert_eq!(index(\u0026array, 3..5), [13, 21]);\n}\n\nconst fn index\u003cT, I\u003e(slice: \u0026[T], idx: I) -\u003e \u0026SliceIndexRet\u003cI, T\u003e\nwhere\n    I: SliceIndex\u003cT\u003e,\n{\n    // `I::WITNESS` is `\u003cI as HasTypeWitness\u003cIndexWitness\u003cI\u003e\u003e\u003e::WITNESS`,\n    match I::WITNESS {\n        IndexWitness::Usize(arg_te) =\u003e {\n            // `arg_te` (a `TypeEq\u003cI, usize\u003e`) allows coercing between `I` and `usize`,\n            // because `TypeEq` is a value-level proof that both types are the same.\n            let idx: usize = arg_te.to_right(idx);\n\n            // using the `TypeFn` impl for `FnSliceIndexRet\u003cT\u003e` to \n            // map `TypeEq\u003cI, usize\u003e` \n            // to  `TypeEq\u003cSliceIndexRet\u003cI, T\u003e, SliceIndexRet\u003cusize, T\u003e\u003e`\n            arg_te.project::\u003cFnSliceIndexRet\u003cT\u003e\u003e()\n                // converts`TypeEq\u003cSliceIndexRet\u003cI, T\u003e, T\u003e` \n                //      to `TypeEq\u003c\u0026SliceIndexRet\u003cI, T\u003e, \u0026T\u003e`\n                .in_ref()\n                .to_left(\u0026slice[idx])\n        }\n        IndexWitness::Range(arg_te) =\u003e {\n            let range: Range\u003cusize\u003e = arg_te.to_right(idx);\n            let ret: \u0026[T] = slice_range(slice, range);\n            arg_te.project::\u003cFnSliceIndexRet\u003cT\u003e\u003e().in_ref().to_left(ret)\n        }\n    }\n}\n\n// This macro declares a type witness enum\ntypewit::simple_type_witness! {\n    // Declares `enum IndexWitness\u003c__Wit\u003e` \n    // (the `__Wit` type parameter is implicitly added after all generics)\n    enum IndexWitness {\n        // This variant requires `__Wit == usize`\n        Usize = usize,\n   \n        // This variant requires `__Wit == Range\u003cusize\u003e`\n        Range = Range\u003cusize\u003e,\n    }\n}\n\n/// Trait for all types that can be used as slice indices\n/// \n/// The `HasTypeWitness` supertrait allows getting a `IndexWitness\u003cSelf\u003e`\n/// with its `WITNESS` associated constant.\ntrait SliceIndex\u003cT\u003e: HasTypeWitness\u003cIndexWitness\u003cSelf\u003e\u003e + Sized {\n    type Returns: ?Sized;\n}\nimpl\u003cT\u003e SliceIndex\u003cT\u003e for usize {\n    type Returns = T;\n}\nimpl\u003cT\u003e SliceIndex\u003cT\u003e for Range\u003cusize\u003e {\n    type Returns = [T];\n}\n\ntype SliceIndexRet\u003cI, T\u003e = \u003cI as SliceIndex\u003cT\u003e\u003e::Returns;\n\n// Declares `struct FnSliceIndexRet\u003cT\u003e`\n// a type-level function (TypeFn implementor) from `I` to `SliceIndexRet\u003cI, T\u003e`\ntypewit::type_fn! {\n    struct FnSliceIndexRet\u003cT\u003e;\n\n    impl\u003cI: SliceIndex\u003cT\u003e\u003e I =\u003e SliceIndexRet\u003cI, T\u003e\n}\n\nconst fn slice_range\u003cT\u003e(slice: \u0026[T], range: Range\u003cusize\u003e) -\u003e \u0026[T] {\n    let suffix = slice.split_at(range.start).1;\n    suffix.split_at(range.end - range.start).0\n}\n\n```\n\nWhen the wrong type is passed for the index,\nthe compile-time error is the same as with normal generic functions:\n```text\nerror[E0277]: the trait bound `RangeFull: SliceIndex\u003c{integer}\u003e` is not satisfied\n  --\u003e src/main.rs:43:30\n   |\n13 |     assert_eq!(index(\u0026array, ..), [13, 21]);\n   |                -----         ^^ the trait `SliceIndex\u003c{integer}\u003e` is not implemented for `RangeFull`\n   |                |\n   |                required by a bound introduced by this call\n   |\n   = help: the following other types implement trait `SliceIndex\u003cT\u003e`:\n             std::ops::Range\u003cusize\u003e\n             usize\n```\n\n### Downcasting const generic type\n\nThis example demonstrates \"downcasting\" from a type with a const parameter to \na concrete instance of that type.\n\n```rust\nuse typewit::{const_marker::Usize, TypeCmp, TypeEq};\n\nassert_eq!(*mutate(\u0026mut Arr([])), Arr([]));\nassert_eq!(*mutate(\u0026mut Arr([1])), Arr([1]));\nassert_eq!(*mutate(\u0026mut Arr([1, 2])), Arr([1, 2]));\nassert_eq!(*mutate(\u0026mut Arr([1, 2, 3])), Arr([1, 3, 6])); // this is different!\nassert_eq!(*mutate(\u0026mut Arr([1, 2, 3, 4])), Arr([1, 2, 3, 4])); \n\n#[derive(Debug, PartialEq)]\nstruct Arr\u003cconst N: usize\u003e([u8; N]);\n\nfn mutate\u003cconst N: usize\u003e(arr: \u0026mut Arr\u003cN\u003e) -\u003e \u0026mut Arr\u003cN\u003e {\n    if let TypeCmp::Eq(te) =  Usize::\u003cN\u003e.equals(Usize::\u003c3\u003e) {\n        let tem = te // `te` is a `TypeEq\u003cUsize\u003cN\u003e, Usize\u003c3\u003e\u003e`\n            .project::\u003cGArr\u003e() // returns `TypeEq\u003cArr\u003cN\u003e, Arr\u003c3\u003e\u003e`\n            .in_mut(); // returns `TypeEq\u003c\u0026mut Arr\u003cN\u003e, \u0026mut Arr\u003c3\u003e\u003e`\n\n        // `tem.to_right(arr)` downcasts `arr` to `\u0026mut Arr\u003c3\u003e`\n        tetra_sum(tem.to_right(arr));\n    }\n\n    arr\n}\n\nfn tetra_sum(arr: \u0026mut Arr\u003c3\u003e) {\n    arr.0[1] += arr.0[0];\n    arr.0[2] += arr.0[1];\n}\n\n// Declares `struct GArr`\n// a type-level function (TypeFn implementor) from `Usize\u003cN\u003e` to `Arr\u003cN\u003e`\ntypewit::type_fn!{\n    struct GArr;\n\n    impl\u003cconst N: usize\u003e Usize\u003cN\u003e =\u003e Arr\u003cN\u003e\n}\n```\n\n### Builder\n\nUsing a type witness to help encode a type-level enum,\nand to match on that type-level enum inside of a function.\n\nThe type-level enum is used to track the initialization of fields in a builder.\n\nThis example requires Rust 1.65.0, because it uses Generic Associated Types.\n```rust\nuse typewit::HasTypeWitness;\n\nfn main() {\n    // all default fields\n    assert_eq!(\n        StructBuilder::new().build(), \n        Struct{foo: \"default value\".into(), bar: vec![3, 5, 8]},\n    );\n\n    // defaulted bar field\n    assert_eq!(\n        StructBuilder::new().foo(\"hello\").build(), \n        Struct{foo: \"hello\".into(), bar: vec![3, 5, 8]},\n    );\n\n    // defaulted foo field\n    assert_eq!(\n        StructBuilder::new().bar([13, 21, 34]).build(), \n        Struct{foo: \"default value\".into(), bar: vec![13, 21, 34]},\n    );\n\n    // all initialized fields\n    assert_eq!(\n        StructBuilder::new().foo(\"world\").bar([55, 89]).build(), \n        Struct{foo: \"world\".into(), bar: vec![55, 89]},\n    );\n}\n\n\n#[derive(Debug, PartialEq, Eq)]\nstruct Struct {\n    foo: String,\n    bar: Vec\u003cu32\u003e,\n}\n\nstruct StructBuilder\u003cFooInit: InitState, BarInit: InitState\u003e {\n    // If `FooInit` is `Uninit`, then this field is a `()`\n    // If `FooInit` is `Init`, then this field is a `String`\n    foo: BuilderField\u003cFooInit, String\u003e,\n\n    // If `BarInit` is `Uninit`, then this field is a `()`\n    // If `BarInit` is `Init`, then this field is a `Vec\u003cu32\u003e`\n    bar: BuilderField\u003cBarInit, Vec\u003cu32\u003e\u003e,\n}\n\nimpl StructBuilder\u003cUninit, Uninit\u003e {\n    pub const fn new() -\u003e Self {\n        Self {\n            foo: (),\n            bar: (),\n        }\n    }\n}\n\nimpl\u003cFooInit: InitState, BarInit: InitState\u003e StructBuilder\u003cFooInit, BarInit\u003e {\n    /// Sets the `foo` field\n    pub fn foo(self, foo: impl Into\u003cString\u003e) -\u003e StructBuilder\u003cInit, BarInit\u003e {\n        StructBuilder {\n            foo: foo.into(),\n            bar: self.bar,\n        }\n    }\n\n    /// Sets the `bar` field\n    pub fn bar(self, bar: impl Into\u003cVec\u003cu32\u003e\u003e) -\u003e StructBuilder\u003cFooInit, Init\u003e {\n        StructBuilder {\n            foo: self.foo,\n            bar: bar.into(),\n        }\n    }\n\n    /// Builds `Struct`, \n    /// providing default values for fields that haven't been set.\n    pub fn build(self) -\u003e Struct {\n        Struct {\n            foo: init_or_else::\u003cFooInit, _, _\u003e(self.foo, || \"default value\".to_string()),\n            bar: init_or_else::\u003cBarInit, _, _\u003e(self.bar, || vec![3, 5, 8]),\n        }\n    }\n}\n\n// Emulates a type-level `enum InitState { Init, Uninit }`\ntrait InitState: Sized + HasTypeWitness\u003cInitWit\u003cSelf\u003e\u003e {\n    // How a builder represents an initialized/uninitialized field.\n    // If `Self` is `Uninit`, then this is `()`.\n    // If `Self` is `Init`, then this is `T`.\n    type BuilderField\u003cT\u003e;\n}\n\n// If `I` is `Uninit`, then this evaluates to `()`\n// If `I` is `Init`, then this evaluates to `T`\ntype BuilderField\u003cI, T\u003e = \u003cI as InitState\u003e::BuilderField::\u003cT\u003e;\n\n/// Gets `T` out of `maybe_init` if it's actually initialized,\n/// otherwise returns `else_()`.\nfn init_or_else\u003cI, T, F\u003e(maybe_init: BuilderField\u003cI, T\u003e, else_: F) -\u003e T\nwhere\n    I: InitState,\n    F: FnOnce() -\u003e T\n{\n    typewit::type_fn! {\n        // Declares the `HelperFn` type-level function (TypeFn implementor)\n        // from `I` to `BuilderField\u003cI, T\u003e`\n        struct HelperFn\u003cT\u003e;\n        impl\u003cI: InitState\u003e I =\u003e BuilderField\u003cI, T\u003e\n    }\n\n    // matching on the type-level `InitState` enum by using `InitWit`.\n    // `WITNESS` comes from the `HasTypeWitness` trait\n    match I::WITNESS {\n        // `te: TypeEq\u003cFooInit, Init\u003e`\n        InitWit::InitW(te) =\u003e {\n            te.map(HelperFn::NEW) //: TypeEq\u003cBuilderField\u003cI, T\u003e, T\u003e\n              .to_right(maybe_init)\n        }\n        InitWit::UninitW(_) =\u003e else_(),\n    }\n}\n\n// Emulates a type-level `InitState::Init` variant.\n// Marks a field as initialized.\nenum Init {}\n\nimpl InitState for Init {\n    type BuilderField\u003cT\u003e = T;\n}\n\n// Emulates a type-level `InitState::Uninit` variant.\n// Marks a field as uninitialized.\nenum Uninit {}\n\nimpl InitState for Uninit {\n    type BuilderField\u003cT\u003e = ();\n}\n\ntypewit::simple_type_witness! {\n    // Declares `enum InitWit\u003c__Wit\u003e`, a type witness.\n    // (the `__Wit` type parameter is implicitly added after all generics)\n    enum InitWit {\n        // This variant requires `__Wit == Init`\n        InitW = Init,\n        // This variant requires `__Wit == Uninit`\n        UninitW = Uninit,\n    }\n}\n```\n\n### Generic Const Expressions\n\nThis example uses [`Usize`] to coerce an arrays whose length is generic to \nanother generic, but equal, length.\n\nThis example requires the `\"generic_const_exprs\"` crate feature because it uses the\ncurrently-unstable [`generic_const_exprs`] language feature.\n\n```rust\n#![feature(generic_const_exprs)]\n\nuse typewit::{const_marker::Usize, TypeCmp, TypeEq};\n\n\nlet mut arrays = Arrays::\u003c1, 3\u003e { a: [3, 5, 8], b: [13, 21, 34] };\n\narrays.swap_inner();\n\nassert_eq!(arrays.a, [13, 21, 34]);\nassert_eq!(arrays.b, [3, 5, 8]);\n\n\nstruct Arrays\u003cconst A: usize, const B: usize\u003e \nwhere\n    [u8; A * B]:, \n    [u8; B * A]:,\n{\n    a: [u8; A * B],\n    b: [u8; B * A],\n}\n\nimpl\u003cconst A: usize, const B: usize\u003e Arrays\u003cA, B\u003e \nwhere\n    [u8; A * B]:, \n    [u8; B * A]:,\n{\n    // Swaps the two array fields\n    const fn swap_inner(\u0026mut self) {\n        let a = TypeEq::new::\u003cu8\u003e() // : TypeEq\u003cu8, u8\u003e\n            .in_array(commutative_proof::\u003cA, B\u003e()) // : TypeEq\u003c[u8; A * B], [u8; B * A]\u003e\n            .in_mut() // : TypeEq\u003c\u0026mut [u8; A * B], \u0026mut [u8; B * A]\u003e\n            .to_right(\n                \u0026mut self.a // : \u0026mut [u8; A * B] \n            ); // : \u0026mut [u8; B * A] \n        \n        core::mem::swap(a, \u0026mut self.b);\n    }\n}\n\nconst fn commutative_proof\u003cconst A: usize, const B: usize\u003e(\n) -\u003e TypeEq\u003cUsize\u003c{A * B}\u003e, Usize\u003c{B * A}\u003e\u003e\n{\n    // panic-safety: A * B == B * A always holds, so this `unwrap_eq` can never panic\n    Usize::\u003c{A * B}\u003e.equals(Usize::\u003c{B * A}\u003e).unwrap_eq()\n}\n\n```\n\nIf you tried to swap the fields directly, you'd get this error:\n```text\nerror[E0308]: mismatched types\n  --\u003e src/lib.rs:437:38\n   |\n42 |         core::mem::swap(\u0026mut self.a, \u0026mut self.b);\n   |                                      ^^^^^^^^^^^ expected `A * B`, found `B * A`\n   |\n   = note: expected constant `A * B`\n              found constant `B * A`\n```\n\n# Cargo features\n\nThese are the features of this crate.\n\n### Default-features\n\nThese features are enabled by default:\n\n- `\"proc_macros\"`: uses proc macros to improve compile-errors involving \nmacro-generated impls.\n\n### Rust-versions and standard crates\n\nThese features enable items that have a minimum Rust version:\n\n- `\"rust_stable\"`: enables all the `\"rust_1_*\"` features.\n\n- `\"rust_1_83\"`: turns functions that take mutable references into `const fn`s,\nand enables the `\"rust_1_65\"` feature.\n\n- `\"rust_1_65\"`: enables the [`type_constructors`] module,\nthe [`methods`] module,\nand the `\"rust_1_61\"` feature.\n\n- `\"rust_1_61\"`: enables [`MetaBaseTypeWit`],\n[`BaseTypeWitness`],\nand the `{TypeCmp, TypeNe}::{zip*, in_array}` methods.\n\nThese features enable items that require a non-`core` standard crate:\n\n- `\"alloc\"`: enable items that use anything from the standard `alloc` crate.\n\n### Nightly features\n\nThese features require the nightly Rust compiler:\n\n- `\"adt_const_marker\"`:\nenables the `\"rust_stable\"` crate feature,\nand marker types in the [`const_marker`] module that have\nnon-primitive `const` parameters.\n\n- `\"generic_const_exprs\"`:\nenables the `\"rust_stable\"` crate feature,\nand doc examples that use the [`generic_const_exprs`] unstable language feature.\n\n# No-std support\n\n`typewit` is `#![no_std]`, it can be used anywhere Rust can be used.\n\nYou need to enable the `\"alloc\"` feature to enable items that use anything \nfrom the standard `alloc` crate.\n\n# Minimum Supported Rust Version\n\n`typewit` supports Rust 1.57.0.\n\nFeatures that require newer versions of Rust, or the nightly compiler,\nneed to be explicitly enabled with crate features.\n\n\n\n\n\n\n[`TypeCmp`]: https://docs.rs/typewit/latest/typewit/enum.TypeCmp.html\n[`TypeEq`]: https://docs.rs/typewit/latest/typewit/struct.TypeEq.html\n[`TypeNe`]: https://docs.rs/typewit/latest/typewit/struct.TypeEq.html\n[`TypeFn`]: https://docs.rs/typewit/latest/typewit/type_fn/trait.TypeFn.html\n[`const_marker`]: https://docs.rs/typewit/latest/typewit/const_marker/index.html\n[`type_constructors`]: https://docs.rs/typewit/latest/typewit/type_constructors/index.html\n[`methods`]: https://docs.rs/typewit/latest/typewit/methods/index.html\n[`MetaBaseTypeWit`]: https://docs.rs/typewit/latest/typewit/enum.MetaBaseTypeWit.html\n[`BaseTypeWitness`]: https://docs.rs/typewit/latest/typewit/trait.BaseTypeWitness.html\n[`Usize`]: https://docs.rs/typewit/latest/typewit/const_marker/struct.Usize.html\n[`generic_const_exprs`]: https://doc.rust-lang.org/unstable-book/language-features/generic-const-exprs.html\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frodrimati1992%2Ftypewit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frodrimati1992%2Ftypewit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frodrimati1992%2Ftypewit/lists"}