Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

1
vendor/typewit/.cargo-checksum.json vendored Normal file
View File

@@ -0,0 +1 @@
{"files":{"Cargo.lock":"a3654f5674dd3b56958246abd729088cc206ad9d02897cec353cb9e4201d5df7","Cargo.toml":"e3b50fffa7d6c8eedec6ddbdfffc22956fae30e40912ccf07acba830b2d8d7f6","LICENSE-ZLIB.md":"6db6d36c8aae8c2f6ebec32965bab9b4769128caed09a55b8696afce4301838a","src/all_init_bytes.rs":"e625be531aec3701ffff613c8a5bf3a53886dbb52c3bbb09ddeed2609d0b32e6","src/all_init_bytes/tests.rs":"0374452587971808549ee8b29ace44f5ea2e3302accd4ece4201031b18dec337","src/base_type_wit.rs":"868e7a5b2a4e42bc1717bc6b659738f1ea7cfffc895a80c02578dcf02ed81a9c","src/base_type_wit/meta_base_type_wit.rs":"0a5cbee6b16f5a03765f56a51790b357d540c1c8aad4e5054bd6b4ea852da49a","src/const_marker.rs":"7c72df059536f0d15e93ae9d2674322132d0c4a55541bb09101c319b993ab231","src/const_marker/boolwit.rs":"a5ed168f17c62595492d9672b1a93a1ab4462554d55773b8e76d12051a04e564","src/const_marker/const_marker_eq_traits.rs":"37394b34394b540496d5396432e023a699be4d43bed2105504c0881d32c3a151","src/const_marker/const_marker_trait.rs":"41ac098b3dcd3a0b782ea25346fd0a8656fd2f0d34084a7680e34f9d43e07648","src/const_marker/slice_const_markers.rs":"be568b1cdc06cf369c17b1834855ce3a063e10f4af8bc6168c54d9381b60f172","src/const_marker/slice_const_markers/tests.rs":"9d61227cc932105f915ae50f8834b55e30850982e531c0dff18d16b14cee18e7","src/lib.rs":"6866ca1e24453e7bc1906520f8a87f0ed4b8796fa5daee1db816fbf0b2db40f6","src/macros.rs":"892a529f171f340984070fb4dc7325ef194ceb2106568e2d27f4bab3955186a3","src/macros/generics_parsing.rs":"33cffe75056626ea3c54bed355a4acb0de81b095f7bb88f555413fd30afc50b2","src/macros/inj_type_fn_macro.rs":"16898d2990e69967341ff8e81e60b97d65d0a8f34f0007a2b96589ac01bd6b25","src/macros/polymatch.rs":"038860ac985842dc378275aaf9a0d9f3ef4a8611ff7db35605da56d59ed6053c","src/macros/simple_type_witness_macro.rs":"bcb7590bee02f48aa353c1ed8a9a0af7763aea4dcc7a76b7beb6aa832271c152","src/macros/type_fn_macro.rs":"4e8090aeb37941e8bdf703c9644eb1488b5df74deea638ba5309632a1bf20bc5","src/macros/type_ne_macro.rs":"0d61c022b27d50da2056e30efeccf774e04c6f0382e8979837e5138471d1ef63","src/methods.rs":"fa31bf8506f471f5e996132f3f071ba5b8fdd52d63a7ec7b57973a14a7def2c6","src/methods/zipping_.rs":"b3a55991509329cb48b72d9cbf3c7769dc48340b67a67ba70542ecaf084c37b4","src/some_type_arg_is_ne.rs":"b2d6e95c0a9b356c6b36f981487b75e0695247a29b0dbc0563ecfe783f7002e4","src/test_doc_lints.rs":"698c8e32e988a08f6d322ebdf9e21d6e4f49d547650a6f96d2fb4fd5860e3876","src/type_cmp.rs":"54e0fe8ba57ec26f81293566ae4ba7b824346bb3985097d6a1784fae27b0ab97","src/type_cmp/extra_type_cmp_methods.rs":"5aba84f8781e636599f6a0bb1395f7aef4ddd5e81fea9c9ac3a6da48d63dd4e2","src/type_constructors.rs":"5da9a875f477c4a773a88d1328b9eaff149b7db02066401fef727387dcbce2e8","src/type_eq.rs":"a4512b0f7e238b4d26f9e1353e44bb476df931f52dd42ac8d52de164621b76d4","src/type_eq_ne_guts.rs":"4d1e1fb9b2bd6c6daa08898652daedd81468a3acbe0999f58dd1f359c4b2412d","src/type_fn.rs":"1a59a84de7294fcd91db74ca848eec54e2f99e7651c40fb5a4b806d1292913b2","src/type_fn/injective.rs":"0fb03a56b8719d0a4b494ddff1725aefa1d9ead688db93718dcaa3aa344f9da5","src/type_identity.rs":"0568dd1e23adbac6c7c6a61439f1b5da2a1a373e6519849d75606e996b54b911","src/type_ne/extra_type_ne_methods.rs":"829c8c4e40476c6b2d7b9dd56727cf25b654b5919b716975598137b4a686f192","src/type_ne_.rs":"de93b75af0d7c93a067f26dad68c206ef55ff924b0e0bd78ae45256c331620da","src/type_witness_traits.rs":"660ffa41a5c13e940ffc3c50cdf37654112e71ae9c16bc6273018adfacab807c","src/utils.rs":"602d7286dc26989194a734929b42fe6836c9748e1257b74f160b15435283a869"},"package":"f8c1ae7cc0fdb8b842d65d127cb981574b0d2b249b74d1c7a2986863dc134f71"}

178
vendor/typewit/Cargo.lock generated vendored Normal file
View File

@@ -0,0 +1,178 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "arrayvec"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
[[package]]
name = "basic-toml"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7bfc506e7a2370ec239e1d072507b2a80c833083699d3c6fa176fbb4de8448c6"
dependencies = [
"serde",
]
[[package]]
name = "glob"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "itoa"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
[[package]]
name = "once_cell"
version = "1.17.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9670a07f94779e00908f3e686eab508878ebb390ba6e604d3a284c00e8d0487b"
[[package]]
name = "proc-macro2"
version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
dependencies = [
"proc-macro2",
]
[[package]]
name = "ryu"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
[[package]]
name = "serde"
version = "1.0.188"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.188"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2cc66a619ed80bf7a0f6b17dd063a84b88f6dea1813737cf469aef1d081142c2"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "syn"
version = "2.0.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "718fa2415bcb8d8bd775917a1bf12a7931b6dfa890753378538118181e0cb398"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "termcolor"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
dependencies = [
"winapi-util",
]
[[package]]
name = "trybuild"
version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6df60d81823ed9c520ee897489573da4b1d79ffbe006b8134f46de1a1aa03555"
dependencies = [
"basic-toml",
"glob",
"once_cell",
"serde",
"serde_derive",
"serde_json",
"termcolor",
]
[[package]]
name = "typewit"
version = "1.14.2"
dependencies = [
"arrayvec",
"trybuild",
"typewit_proc_macros",
]
[[package]]
name = "typewit_proc_macros"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e36a83ea2b3c704935a01b4642946aadd445cea40b10935e3f8bd8052b8193d6"
[[package]]
name = "unicode-ident"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

87
vendor/typewit/Cargo.toml vendored Normal file
View File

@@ -0,0 +1,87 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2021"
rust-version = "1.57.0"
name = "typewit"
version = "1.14.2"
authors = ["rodrimati1992 <rodrimatt1985@gmail.com>"]
build = false
include = [
"Cargo.toml",
"src/**/*.rs",
"./README.md",
"LICENSE-ZLIB.md",
]
autolib = false
autobins = false
autoexamples = false
autotests = false
autobenches = false
description = "type-witness-based abstractions, mostly for emulating polymorphism in const fns"
documentation = "https://docs.rs/typewit/"
readme = "README.md"
keywords = [
"const_fn",
"GADT",
"type_witness",
"type-equality",
"refl",
]
categories = [
"no-std",
"rust-patterns",
]
license = "Zlib"
repository = "https://github.com/rodrimati1992/typewit/"
[package.metadata.docs.rs]
features = [
"alloc",
"rust_stable",
"adt_const_marker",
"generic_const_exprs",
"docsrs",
]
[features]
__test_doc_lints = []
__ui_tests = ["trybuild"]
adt_const_marker = ["rust_stable"]
alloc = []
const_marker = []
default = ["proc_macros"]
docsrs = []
generic_const_exprs = ["rust_stable"]
mut_refs = ["rust_stable"]
nightly_mut_refs = ["mut_refs"]
proc_macros = ["typewit_proc_macros"]
rust_1_61 = []
rust_1_65 = ["rust_1_61"]
rust_1_83 = ["rust_1_65"]
rust_stable = ["rust_1_83"]
[lib]
name = "typewit"
path = "src/lib.rs"
[dependencies.trybuild]
version = "1.0"
optional = true
[dependencies.typewit_proc_macros]
version = "=1.8.1"
optional = true
[dev-dependencies.arrayvec]
version = "0.7"
default-features = false

17
vendor/typewit/LICENSE-ZLIB.md vendored Normal file
View File

@@ -0,0 +1,17 @@
Copyright (c) 2023 Matias Rodriguez.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.

44
vendor/typewit/src/all_init_bytes.rs vendored Normal file
View File

@@ -0,0 +1,44 @@
#[cfg(test)]
mod tests;
/// Marker trait for type for which all bytes are initialized
///
/// # Safety
///
/// All of the bytes in this type must be initialized.
/// Uninitialized bytes includes padding and `MaybeUninit` fields.
pub(crate) unsafe trait AllInitBytes {}
#[allow(dead_code)]
pub(crate) const fn as_bytes<T: AllInitBytes>(reff: &T) -> &[u8] {
unsafe {
core::slice::from_raw_parts (
reff as *const T as *const u8,
core::mem::size_of::<T>(),
)
}
}
pub(crate) const fn slice_as_bytes<T: AllInitBytes>(reff: &[T]) -> &[u8] {
unsafe {
core::slice::from_raw_parts (
reff.as_ptr() as *const u8,
reff.len() * core::mem::size_of::<T>(),
)
}
}
unsafe impl AllInitBytes for bool {}
unsafe impl AllInitBytes for char {}
unsafe impl AllInitBytes for u8 {}
unsafe impl AllInitBytes for u16 {}
unsafe impl AllInitBytes for u32 {}
unsafe impl AllInitBytes for u64 {}
unsafe impl AllInitBytes for u128 {}
unsafe impl AllInitBytes for usize {}
unsafe impl AllInitBytes for i8 {}
unsafe impl AllInitBytes for i16 {}
unsafe impl AllInitBytes for i32 {}
unsafe impl AllInitBytes for i64 {}
unsafe impl AllInitBytes for i128 {}
unsafe impl AllInitBytes for isize {}

View File

@@ -0,0 +1,116 @@
use super::{as_bytes, slice_as_bytes};
macro_rules! test_int {
($vals:expr) => ({
for val in $vals {
assert_eq!(as_bytes(&val), val.to_ne_bytes());
let mut vec = arrayvec::ArrayVec::<u8, 32>::new();
vec.try_extend_from_slice(&val.to_ne_bytes()).unwrap();
vec.try_extend_from_slice(&val.to_ne_bytes()).unwrap();
assert_eq!(slice_as_bytes(&[val, val]), &vec[..]);
}
});
}
macro_rules! test_signed_int {
($vals:expr) => ({
for val in $vals {
test_int!{[val, -val]}
}
});
}
#[test]
fn test_bool_as_bytes() {
for b in [false, true] {
assert_eq!(as_bytes(&b), &[b as u8][..]);
assert_eq!(slice_as_bytes(&[b]), &[b as u8][..]);
}
}
#[test]
fn test_char_as_bytes() {
for c in ['f', 'o', '\n', '\t', 'ñ', '个', '\u{100000}', char::MAX] {
assert_eq!(as_bytes(&c), (c as u32).to_ne_bytes());
assert_eq!(slice_as_bytes(&[c]), (c as u32).to_ne_bytes());
}
}
#[test]
fn test_u8_as_bytes() {
test_int!{[0u8, 233u8]}
}
#[test]
fn test_u16_as_bytes() {
test_int!{[0u16, 500u16, 1000u16]}
}
#[test]
fn test_u32_as_bytes() {
test_int!{[0u32, 500u32, 1000u32, 1_000_000u32, 1_000_000_000u32]}
}
#[test]
fn test_u64_as_bytes() {
test_int!{[
0u64, 500u64, 1000u64, 1_000_000u64, 1_000_000_000u64,
1_000_000_000_000_000_000u64,
]}
}
#[test]
fn test_u128_as_bytes() {
test_int!{[
0u128, 500u128, 1000u128, 1_000_000u128, 1_000_000_000u128,
1_000_000_000_000_000_000u128, 1_000_000_000_000_000_000_000_000_000u128,
1_000_000_000_000_000_000_000_000_000_000_000_000u128,
]}
}
#[test]
fn test_usize_as_bytes() {
test_int!{[0usize, 500usize, 1000usize, 12345usize]}
}
#[test]
fn test_i8_as_bytes() {
test_signed_int!{[0i8, 111i8]}
}
#[test]
fn test_i16_as_bytes() {
test_signed_int!{[0i16, 500i16, 1000i16]}
}
#[test]
fn test_i32_as_bytes() {
test_signed_int!{[0i32, 500i32, 1000i32, 1_000_000i32, 1_000_000_000i32]}
}
#[test]
fn test_i64_as_bytes() {
test_signed_int!{[
0i64, 500i64, 1000i64, 1_000_000i64, 1_000_000_000i64,
1_000_000_000_000_000_000i64,
]}
}
#[test]
fn test_i128_as_bytes() {
test_signed_int!{[
0i128, 500i128, 1000i128, 1_000_000i128, 1_000_000_000i128,
1_000_000_000_000_000_000i128, 1_000_000_000_000_000_000_000_000_000i128,
1_000_000_000_000_000_000_000_000_000_000_000_000i128,
]}
}
#[test]
fn test_isize_as_bytes() {
test_signed_int!{[0isize, 500isize, 1000isize, 12345isize]}
}

62
vendor/typewit/src/base_type_wit.rs vendored Normal file
View File

@@ -0,0 +1,62 @@
//! abstractions over
//! [`TypeEq`](crate::TypeEq)/[`TypeNe`](crate::TypeNe)/[`TypeCmp`](crate::TypeCmp).
mod meta_base_type_wit;
pub use meta_base_type_wit::MetaBaseTypeWit;
/// Marker trait for
/// [`TypeCmp`](crate::TypeCmp)/[`TypeEq`](crate::TypeEq)/[`TypeNe`](crate::TypeNe).
///
/// [`TypeEq`]: crate::TypeEq
/// [`TypeNe`]: crate::TypeNe
/// [`TypeCmp`]: crate::TypeCmp
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_61")))]
pub trait BaseTypeWitness:
core::fmt::Debug +
Copy +
crate::HasTypeWitness<MetaBaseTypeWit<Self::L, Self::R, Self>>
{
/// The `L` type parameter of `TypeEq`/`TypeNe`/`TypeCmp` types.
type L: ?Sized;
/// The `R` type parameter of `TypeEq`/`TypeNe`/`TypeCmp` types.
type R: ?Sized;
/// The [type constructor] corresponding to this type.
///
/// [type constructor]: crate::type_constructors::BaseTypeWitnessTc
#[cfg(feature = "rust_1_65")]
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_65")))]
type TypeCtor: crate::type_constructors::BaseTypeWitnessTc<Type<Self::L, Self::R> = Self>;
}
impl<L: ?Sized, R: ?Sized> BaseTypeWitness for crate::TypeEq<L, R> {
type L = L;
type R = R;
#[cfg(feature = "rust_1_65")]
type TypeCtor = crate::type_constructors::TcTypeEq;
}
impl<L: ?Sized, R: ?Sized> BaseTypeWitness for crate::TypeNe<L, R> {
type L = L;
type R = R;
#[cfg(feature = "rust_1_65")]
type TypeCtor = crate::type_constructors::TcTypeNe;
}
impl<L: ?Sized, R: ?Sized> BaseTypeWitness for crate::TypeCmp<L, R> {
type L = L;
type R = R;
#[cfg(feature = "rust_1_65")]
type TypeCtor = crate::type_constructors::TcTypeCmp;
}

View File

@@ -0,0 +1,64 @@
use crate::{MakeTypeWitness, TypeWitnessTypeArg, TypeEq, TypeNe, TypeCmp};
use core::fmt::{self, Debug};
/// Type witness for
/// [`TypeEq`](crate::TypeEq)/[`TypeNe`](crate::TypeNe)/[`TypeCmp`](crate::TypeCmp).
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_61")))]
pub enum MetaBaseTypeWit<L: ?Sized, R: ?Sized, W> {
/// `where W == TypeEq<L, R>`
Eq(TypeEq<W, TypeEq<L, R>>),
/// `where W == TypeNe<L, R>`
Ne(TypeEq<W, TypeNe<L, R>>),
/// `where W == TypeCmp<L, R>`
Cmp(TypeEq<W, TypeCmp<L, R>>),
}
impl<L: ?Sized, R: ?Sized, W> MetaBaseTypeWit<L, R, W> {
/// Converts `W` to `TypeCmp<L, R>`
pub const fn to_cmp(self, witness: W) -> TypeCmp<L, R> {
match self {
Self::Cmp(te) => te.to_right(witness),
Self::Eq(te) => TypeCmp::Eq(te.to_right(witness)),
Self::Ne(te) => TypeCmp::Ne(te.to_right(witness)),
}
}
}
impl<L: ?Sized, R: ?Sized, W> Copy for MetaBaseTypeWit<L, R, W> {}
impl<L: ?Sized, R: ?Sized, W> Clone for MetaBaseTypeWit<L, R, W> {
fn clone(&self) -> Self {
*self
}
}
impl<L: ?Sized, R: ?Sized, W> Debug for MetaBaseTypeWit<L, R, W> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let isa = match self {
Self::Eq{..} => "TypeEq",
Self::Ne{..} => "TypeNe",
Self::Cmp{..} => "TypeCmp",
};
f.write_str(isa)
}
}
impl<L: ?Sized, R: ?Sized, W> TypeWitnessTypeArg for MetaBaseTypeWit<L, R, W> {
type Arg = W;
}
impl<L: ?Sized, R: ?Sized> MakeTypeWitness for MetaBaseTypeWit<L, R, TypeCmp<L, R>> {
const MAKE: Self = Self::Cmp(TypeEq::NEW);
}
impl<L: ?Sized, R: ?Sized> MakeTypeWitness for MetaBaseTypeWit<L, R, TypeEq<L, R>> {
const MAKE: Self = Self::Eq(TypeEq::NEW);
}
impl<L: ?Sized, R: ?Sized> MakeTypeWitness for MetaBaseTypeWit<L, R, TypeNe<L, R>> {
const MAKE: Self = Self::Ne(TypeEq::NEW);
}

338
vendor/typewit/src/const_marker.rs vendored Normal file
View File

@@ -0,0 +1,338 @@
//! Marker types for passing constants as type arguments.
//!
//! # Example
//!
//! This example emulates specialization,
//! eliding a `.clone()` call when the created array is only one element long.
//!
//! ```rust
//! use typewit::{const_marker::Usize, TypeCmp, TypeEq};
//!
//! let arr = [3u8, 5, 8];
//!
//! assert_eq!(repeat(3), []);
//! assert_eq!(repeat(3), [3]);
//! assert_eq!(repeat(3), [3, 3]);
//! assert_eq!(repeat(3), [3, 3, 3]);
//! assert_eq!(repeat(3), [3, 3, 3, 3]);
//!
//!
//! fn repeat<T: Clone, const OUT: usize>(val: T) -> [T; OUT] {
//! // `te_len` ìs a `TypeEq<Usize<OUT>, Usize<1>>`
//! if let TypeCmp::Eq(te_len) = Usize::<OUT>.equals(Usize::<1>) {
//! // This branch is ran when `OUT == 1`
//! TypeEq::new::<T>() // returns `TypeEq<T, T>`
//! .in_array(te_len) // returns `TypeEq<[T; OUT], [T; 1]>`
//! .to_left([val]) // goes from `[T; 1]` to `[T; OUT]`
//! } else {
//! // This branch is ran when `OUT != 1`
//! [(); OUT].map(|_| val.clone())
//! }
//! }
//! ```
//!
//!
use crate::{
TypeEq,
TypeNe,
};
mod const_marker_trait;
pub use const_marker_trait::*;
#[cfg(feature = "rust_1_83")]
mod const_marker_eq_traits;
#[cfg(feature = "rust_1_83")]
pub use const_marker_eq_traits::*;
mod boolwit;
pub use boolwit::*;
#[cfg(feature = "adt_const_marker")]
mod slice_const_markers;
#[cfg(feature = "adt_const_marker")]
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "adt_const_marker")))]
pub use slice_const_markers::Str;
/// Marker types for `const FOO: &'static [T]` parameters.
#[cfg(feature = "adt_const_marker")]
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "adt_const_marker")))]
pub mod slice {
pub use super::slice_const_markers::{
BoolSlice,
CharSlice,
U8Slice,
U16Slice,
U32Slice,
U64Slice,
U128Slice,
UsizeSlice,
I8Slice,
I16Slice,
I32Slice,
I64Slice,
I128Slice,
IsizeSlice,
StrSlice,
};
}
struct Helper<L, R>(L, R);
macro_rules! __const_eq_with {
($L:expr, $R:expr) => {
$L == $R
};
($L:expr, $R:expr, ($L2:ident, $R2:ident) $cmp:expr) => ({
let $L2 = $L;
let $R2 = $R;
$cmp
});
} pub(crate) use __const_eq_with;
macro_rules! declare_const_param_type {
($($params:tt)*) => {
$crate::const_marker::__declare_const_param_type!{ $($params)* }
#[cfg(feature = "rust_1_83")]
$crate::const_marker::__const_marker_impls!{ $($params)* }
}
} pub(crate) use declare_const_param_type;
macro_rules! __declare_const_param_type {
(
$(#[$struct_docs:meta])*
$struct:ident($prim:ty)
$(
$(#[$eq_docs:meta])*
fn equals $(($L:ident, $R:ident) $comparator:block)?;
)?
) => {
#[doc = concat!(
"Marker type for passing `const VAL: ", stringify!($prim),
"` as a type parameter."
)]
$(#[$struct_docs])*
#[derive(Copy, Clone)]
pub struct $struct<const VAL: $prim>;
impl<const VAL: $prim> crate::const_marker::ConstMarker for $struct<VAL> {
const VAL: Self::Of = VAL;
type Of = $prim;
}
impl<const L: $prim, const R: $prim> $crate::const_marker::Helper<$struct<L>, $struct<R>> {
const EQ: Result<
TypeEq<$struct<L>, $struct<R>>,
TypeNe<$struct<L>, $struct<R>>,
> = if crate::const_marker::__const_eq_with!(
L,
R
$($(, ($L, $R) $comparator)?)?
) {
// SAFETY: `L == R` (both are std types with sensible Eq impls)
// therefore `$struct<L> == $struct<R>`
unsafe {
Ok(TypeEq::<$struct<L>, $struct<R>>::new_unchecked())
}
} else {
// SAFETY: `L != R` (both are std types with sensible Eq impls)
// therefore `$struct<L> != $struct<R>`
unsafe {
Err(TypeNe::<$struct<L>, $struct<R>>::new_unchecked())
}
};
const EQUALS: crate::TypeCmp<$struct<L>, $struct<R>> = match Self::EQ {
Ok(x) => crate::TypeCmp::Eq(x),
Err(x) => crate::TypeCmp::Ne(x),
};
}
impl<const VAL: $prim> $struct<VAL> {
/// Compares `self` and `other` for equality.
///
/// Returns:
/// - `Ok(TypeEq)`: if `VAL == OTHER`
/// - `Err(TypeNe)`: if `VAL != OTHER`
///
#[inline(always)]
#[deprecated(note = "superceeded by `equals` method", since = "1.8.0")]
pub const fn eq<const OTHER: $prim>(
self,
_other: $struct<OTHER>,
) -> Result<
TypeEq<$struct<VAL>, $struct<OTHER>>,
TypeNe<$struct<VAL>, $struct<OTHER>>,
> {
$crate::const_marker::Helper::<$struct<VAL>, $struct<OTHER>>::EQ
}
/// Compares `self` and `other` for equality.
///
/// Returns:
/// - `TypeCmp::Eq(TypeEq)`: if `VAL == OTHER`
/// - `TypeCmp::Ne(TypeNe)`: if `VAL != OTHER`
///
$($(#[$eq_docs])*)?
#[inline(always)]
pub const fn equals<const OTHER: $prim>(
self,
_other: $struct<OTHER>,
) -> crate::TypeCmp<$struct<VAL>, $struct<OTHER>> {
$crate::const_marker::Helper::<$struct<VAL>, $struct<OTHER>>::EQUALS
}
}
/////////
impl<const VAL: $prim> core::fmt::Debug for $struct<VAL> {
fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
core::fmt::Debug::fmt(&VAL, fmt)
}
}
impl<const L: $prim, const R: $prim> core::cmp::PartialEq<$struct<R>> for $struct<L> {
fn eq(&self, _: &$struct<R>) -> bool {
L == R
}
}
impl<const VAL: $prim> core::cmp::Eq for $struct<VAL> {}
};
} pub(crate) use __declare_const_param_type;
declare_const_param_type!{
Bool(bool)
///
/// For getting a type witness that
/// `Bool<B>` is either `Bool<true>` or `Bool<false>`,
/// you can use [`BoolWit`].
///
fn equals;
}
declare_const_param_type!{Char(char)}
declare_const_param_type!{U8(u8)}
declare_const_param_type!{U16(u16)}
declare_const_param_type!{U32(u32)}
declare_const_param_type!{U64(u64)}
declare_const_param_type!{U128(u128)}
declare_const_param_type!{
Usize(usize)
/// # Examples
///
/// ### Array
///
/// This example demonstrates how `Usize` can be used to
/// specialize behavior on array length.
///
/// (this example requires Rust 1.61.0, because it uses trait bounds in const fns)
#[cfg_attr(not(feature = "rust_1_61"), doc = "```ignore")]
#[cfg_attr(feature = "rust_1_61", doc = "```rust")]
/// use typewit::{const_marker::Usize, TypeCmp, TypeEq};
///
/// assert_eq!(try_from_pair::<_, 0>((3, 5)), Ok([]));
/// assert_eq!(try_from_pair::<_, 1>((3, 5)), Ok([3]));
/// assert_eq!(try_from_pair::<_, 2>((3, 5)), Ok([3, 5]));
/// assert_eq!(try_from_pair::<_, 3>((3, 5)), Err((3, 5)));
///
///
/// const fn try_from_pair<T: Copy, const LEN: usize>(pair: (T, T)) -> Result<[T; LEN], (T, T)> {
/// if let TypeCmp::Eq(te_len) = Usize::<LEN>.equals(Usize::<0>) {
/// // this branch is ran on `LEN == 0`
/// // `te_len` is a `TypeEq<Usize<LEN>, Usize<0>>`
/// Ok(
/// TypeEq::new::<T>() // `TypeEq<T, T>`
/// .in_array(te_len) // `TypeEq<[T; LEN], [T; 0]>`
/// .to_left([]) // Goes from `[T; 0]` to `[T; LEN]`
/// )
/// } else if let TypeCmp::Eq(te_len) = Usize.equals(Usize) {
/// // this branch is ran on `LEN == 1`
/// // `te_len` is inferred to be `TypeEq<Usize<LEN>, Usize<1>>`
/// Ok(TypeEq::NEW.in_array(te_len).to_left([pair.0]))
/// } else if let TypeCmp::Eq(te_len) = Usize.equals(Usize) {
/// // this branch is ran on `LEN == 2`
/// // `te_len` is inferred to be `TypeEq<Usize<LEN>, Usize<2>>`
/// Ok(TypeEq::NEW.in_array(te_len).to_left([pair.0, pair.1]))
/// } else {
/// Err(pair)
/// }
/// }
///
/// ```
///
/// ### Struct
///
/// This example demonstrates how `Usize` can be used to pass a
/// const-generic struct to a function expecting a concrete type of that struct.
///
/// ```rust
/// use typewit::{const_marker::Usize, TypeCmp};
///
/// assert_eq!(mutate(Array([])), Array([]));
/// assert_eq!(mutate(Array([3])), Array([3]));
/// assert_eq!(mutate(Array([3, 5])), Array([3, 5]));
/// assert_eq!(mutate(Array([3, 5, 8])), Array([8, 5, 3])); // reversed!
/// assert_eq!(mutate(Array([3, 5, 8, 13])), Array([3, 5, 8, 13]));
///
///
/// #[derive(Debug, PartialEq)]
/// struct Array<const CAP: usize>([u32; CAP]);
///
/// const fn mutate<const LEN: usize>(arr: Array<LEN>) -> Array<LEN> {
/// match Usize::<LEN>.equals(Usize::<3>) {
/// // `te_len` is a `TypeEq<Usize<LEN>, Usize<3>>`
/// // this branch is ran on `LEN == 3`
/// TypeCmp::Eq(te_len) => {
/// // `te` is a `TypeEq<Array<LEN>, Array<3>>`
/// let te = te_len.project::<GArray>();
///
/// // `te.to_right(...)` here goes from `Array<LEN>` to `Array<3>`
/// let ret = reverse3(te.to_right(arr));
///
/// // `te.to_left(...)` here goes from `Array<3>` to `Array<LEN>`
/// te.to_left(ret)
/// }
/// TypeCmp::Ne(_) => arr,
/// }
/// }
///
/// const fn reverse3(Array([a, b, c]): Array<3>) -> Array<3> {
/// Array([c, b, a])
/// }
///
/// typewit::type_fn!{
/// // Type-level function from `Usize<LEN>` to `Array<LEN>`
/// struct GArray;
///
/// impl<const LEN: usize> Usize<LEN> => Array<LEN>
/// }
/// ```
fn equals;
}
declare_const_param_type!{I8(i8)}
declare_const_param_type!{I16(i16)}
declare_const_param_type!{I32(i32)}
declare_const_param_type!{I64(i64)}
declare_const_param_type!{I128(i128)}
declare_const_param_type!{Isize(isize)}

View File

@@ -0,0 +1,393 @@
use core::fmt::{self, Debug};
use crate::{
const_marker::Bool,
TypeCmp,
TypeEq,
TypeWitnessTypeArg, MakeTypeWitness,
};
/// Type Witness that [`Bool<B>`](Bool) is either `Bool<true>` or `Bool<false>`.
///
/// Use this over [`BoolWitG`] if you have a `const B: bool` parameter already.
///
/// # Example
///
/// Making a function that takes a generic `Foo<B>` and calls methods on
/// `Foo<false>` or `Foo<true>` depending on the value of the `const B: bool` parameter.
///
/// ```rust
/// use typewit::{const_marker::{Bool, BoolWit}, MakeTypeWitness};
///
///
/// assert_eq!(call_next(Incrementor::<GO_UP>(4)), Incrementor(5));
/// assert_eq!(call_next(Incrementor::<GO_UP>(5)), Incrementor(6));
///
/// assert_eq!(call_next(Incrementor::<GO_DOWN>(4)), Incrementor(3));
/// assert_eq!(call_next(Incrementor::<GO_DOWN>(3)), Incrementor(2));
///
///
/// const fn call_next<const B: bool>(incrementor: Incrementor<B>) -> Incrementor<B> {
/// typewit::type_fn! {
/// // type-level function from `Bool<B>` to `Incrementor<B>`
/// struct IncrementorFn;
/// impl<const B: bool> Bool<B> => Incrementor<B>
/// }
///
/// // The example below this one shows how to write this match more concisely
/// match BoolWit::MAKE {
/// // `bw: TypeEq<Bool<B>, Bool<true>>`
/// BoolWit::True(bw) => {
/// // `te: TypeEq<Incrementor<B>, Incrementor<true>>`
/// let te = bw.project::<IncrementorFn>();
///
/// // `te.to_right` casts `Incrementor<B>` to `Incrementor<true>`,
/// // (this allows calling the inherent method).
/// //
/// // `te.to_left` casts `Incrementor<true>` to `Incrementor<B>`
/// te.to_left(te.to_right(incrementor).next())
/// }
/// // `bw: TypeEq<Bool<B>, Bool<false>>`
/// BoolWit::False(bw) => {
/// // `te: TypeEq<Incrementor<B>, Incrementor<false>>`
/// let te = bw.project::<IncrementorFn>();
///
/// // like the other branch, but with `Incrementor<false>`
/// te.to_left(te.to_right(incrementor).next())
/// }
/// }
/// }
///
///
/// #[derive(Debug, Copy, Clone, PartialEq, Eq)]
/// struct Incrementor<const GO_UP: bool>(usize);
///
/// const GO_UP: bool = true;
/// const GO_DOWN: bool = false;
///
/// impl Incrementor<GO_DOWN> {
/// #[track_caller]
/// pub const fn next(self) -> Self {
/// Self(self.0 - 1)
/// }
/// }
///
/// impl Incrementor<GO_UP> {
/// pub const fn next(self) -> Self {
/// Self(self.0 + 1)
/// }
/// }
///
/// ```
///
/// ### Using `polymatch` for conciseness
///
/// The [`polymatch`](crate::polymatch) macro can be used to
/// more concisely implement the `call_next` function.
///
/// ```
/// # use typewit::{const_marker::{Bool, BoolWit}, MakeTypeWitness};
/// #
/// const fn call_next<const B: bool>(incrementor: Incrementor<B>) -> Incrementor<B> {
/// typewit::type_fn! {
/// struct IncrementorFn;
/// impl<const B: bool> Bool<B> => Incrementor<B>
/// }
///
/// // expands to a match with two arms,
/// // one for `BoolWit::True` and one for `BoolWit::False`,
/// // copying the expression to the right of the `=>` to both arms.
/// typewit::polymatch! {BoolWit::MAKE;
/// BoolWit::True(bw) | BoolWit::False(bw) => {
/// let te = bw.project::<IncrementorFn>();
/// te.to_left(te.to_right(incrementor).next())
/// }
/// }
/// }
/// #
/// # #[derive(Debug, Copy, Clone, PartialEq, Eq)]
/// # struct Incrementor<const GO_UP: bool>(usize);
/// #
/// # const GO_UP: bool = true;
/// # const GO_DOWN: bool = false;
/// #
/// # impl Incrementor<GO_DOWN> {
/// # #[track_caller]
/// # pub const fn next(self) -> Self { unimplemented!() }
/// # }
/// #
/// # impl Incrementor<GO_UP> {
/// # pub const fn next(self) -> Self { unimplemented!() }
/// # }
/// ```
///
/// ### What happens without `BoolWit`
///
/// If the `call_next` function was defined like this:
/// ```rust,compile_fail
/// # use typewit::{const_marker::{Bool, BoolWit}, MakeTypeWitness};
/// #
/// const fn call_next<const B: bool>(incrementor: Incrementor<B>) -> Incrementor<B> {
/// incrementor.next()
/// }
/// # #[derive(Copy, Clone)]
/// # struct Incrementor<const WRAPPING: bool>(usize);
/// #
/// # impl Incrementor<false> {
/// # pub const fn next(self) -> Self {
/// # unimplemented!()
/// # }
/// # }
/// #
/// # impl Incrementor<true> {
/// # pub const fn next(self) -> Self {
/// # unimplemented!()
/// # }
/// # }
/// ```
/// it would produce this error
/// ```text
/// error[E0599]: no method named `next` found for struct `Incrementor<B>` in the current scope
/// --> src/const_marker/const_witnesses.rs:20:17
/// |
/// 7 | incrementor.next()
/// | ^^^^ method not found in `Incrementor<B>`
/// ...
/// 38 | struct Incrementor<const WRAPPING: bool>(usize);
/// | ---------------------------------------- method `next` not found for this struct
/// |
/// = note: the method was found for
/// - `Incrementor<false>`
/// - `Incrementor<true>`
/// ```
///
///
pub type BoolWit<const B: bool> = BoolWitG<Bool<B>>;
/// Type witness that `B` is either [`Bool`]`<true>` or [`Bool`]`<false>`
///
/// Use this over [`BoolWit`] if you want to write a [`HasTypeWitness`] bound
/// and adding a `const B: bool` parameter would be impossible.
///
/// # Example
///
/// This basic example demonstrates where `BoolWitG` would be used instead of `BoolWit`.
///
/// ```rust
/// use typewit::const_marker::{Bool, BoolWitG};
/// use typewit::HasTypeWitness;
///
///
/// trait Boolean: Sized + HasTypeWitness<BoolWitG<Self>> {
/// type Not: Boolean<Not = Self>;
/// }
///
/// impl Boolean for Bool<true> {
/// type Not = Bool<false>;
/// }
///
/// impl Boolean for Bool<false> {
/// type Not = Bool<true>;
/// }
/// ```
///
/// [`HasTypeWitness`]: crate::HasTypeWitness
pub enum BoolWitG<B> {
/// Witnesses that `B == true`
True(TypeEq<B, Bool<true>>),
/// Witnesses that `B == false`
False(TypeEq<B, Bool<false>>),
}
impl<B> BoolWitG<B> {
/// Whether `B == Bool<true>`
///
/// # Example
///
/// ```rust
/// use typewit::{const_marker::BoolWitG, TypeEq};
///
/// assert_eq!(BoolWitG::True(TypeEq::NEW).is_true(), true);
/// assert_eq!(BoolWitG::False(TypeEq::NEW).is_true(), false);
/// ```
///
pub const fn is_true(self) -> bool {
matches!(self, Self::True{..})
}
/// Whether `B == Bool<false>`
///
/// # Example
///
/// ```rust
/// use typewit::{const_marker::BoolWitG, TypeEq};
///
/// assert_eq!(BoolWitG::True(TypeEq::NEW).is_false(), false);
/// assert_eq!(BoolWitG::False(TypeEq::NEW).is_false(), true);
/// ```
///
pub const fn is_false(self) -> bool {
matches!(self, Self::False{..})
}
/// Gets a proof of `B == Bool<true>`, returns None if `B == Bool<false>`
///
/// # Example
///
/// ```rust
/// use typewit::{const_marker::{Bool, BoolWitG}, TypeEq};
///
/// assert_eq!(BoolWitG::True(TypeEq::NEW).to_true(), Some(TypeEq::new::<Bool<true>>()));
/// assert_eq!(BoolWitG::False(TypeEq::NEW).to_true(), None);
/// ```
///
pub const fn to_true(self) -> Option<TypeEq<B, Bool<true>>> {
match self {
Self::True(x) => Some(x),
Self::False{..} => None
}
}
/// Gets a proof of `B == Bool<false>`, returns None if `B == Bool<true>`
///
/// # Example
///
/// ```rust
/// use typewit::{const_marker::{Bool, BoolWitG}, TypeEq};
///
/// assert_eq!(BoolWitG::True(TypeEq::NEW).to_false(), None);
/// assert_eq!(BoolWitG::False(TypeEq::NEW).to_false(), Some(TypeEq::new::<Bool<false>>()));
/// ```
///
pub const fn to_false(self) -> Option<TypeEq<B, Bool<false>>> {
match self {
Self::False(x) => Some(x),
Self::True{..} => None
}
}
/// Gets a proof of `B == Bool<true>`.
///
/// # Panic
///
/// Panics if `B == Bool<false>`
///
/// # Example
///
/// ```rust
/// use typewit::{const_marker::{Bool, BoolWitG}, TypeEq};
///
/// assert_eq!(BoolWitG::True(TypeEq::NEW).unwrap_true(), TypeEq::new::<Bool<true>>());
/// ```
///
pub const fn unwrap_true(self) -> TypeEq<B, Bool<true>> {
match self {
Self::True(x) => x,
Self::False{..} => panic!("attempted to unwrap into True on False variant")
}
}
/// Gets a proof of `B == Bool<true>`.
///
/// # Panic
///
/// Panics if `B == Bool<false>`, with `msg` as the panic message.
///
/// # Example
///
/// ```rust
/// use typewit::{const_marker::{Bool, BoolWitG}, TypeEq};
///
/// assert_eq!(BoolWitG::True(TypeEq::NEW).expect_true(":("), TypeEq::new::<Bool<true>>());
/// ```
///
pub const fn expect_true(self, msg: &str) -> TypeEq<B, Bool<true>> {
match self {
Self::True(x) => x,
Self::False{..} => panic!("{}", msg)
}
}
/// Gets a proof of `B == Bool<false>`.
///
/// # Panic
///
/// Panics if `B == Bool<true>`
///
/// # Example
///
/// ```rust
/// use typewit::{const_marker::{Bool, BoolWitG}, TypeEq};
///
/// assert_eq!(BoolWitG::False(TypeEq::NEW).unwrap_false(), TypeEq::new::<Bool<false>>());
/// ```
///
pub const fn unwrap_false(self) -> TypeEq<B, Bool<false>> {
match self {
Self::False(x) => x,
Self::True{..} => panic!("attempted to unwrap into False on True variant")
}
}
/// Gets a proof of `B == Bool<false>`.
///
/// # Panic
///
/// Panics if `B == Bool<true>`, with `msg` as the panic message.
///
/// # Example
///
/// ```rust
/// use typewit::{const_marker::{Bool, BoolWitG}, TypeEq};
///
/// assert_eq!(
/// BoolWitG::False(TypeEq::NEW).expect_false("it is false"),
/// TypeEq::new::<Bool<false>>(),
/// );
/// ```
///
pub const fn expect_false(self, msg: &str) -> TypeEq<B, Bool<false>> {
match self {
Self::False(x) => x,
Self::True{..} => panic!("{}", msg)
}
}
}
impl<B> Copy for BoolWitG<B> {}
impl<B> Clone for BoolWitG<B> {
fn clone(&self) -> Self {
*self
}
}
impl<B> Debug for BoolWitG<B> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(match self {
Self::True{..} => "True",
Self::False{..} => "False",
})
}
}
impl<B> TypeWitnessTypeArg for BoolWitG<B> {
type Arg = B;
}
impl<const B: bool> MakeTypeWitness for BoolWitG<Bool<B>> {
const MAKE: Self = {
if let TypeCmp::Eq(te) = Bool.equals(Bool) {
BoolWit::True(te)
} else if let TypeCmp::Eq(te) = Bool.equals(Bool) {
BoolWit::False(te)
} else {
panic!("unreachable: `B` is either `true` or `false`")
}
};
}

View File

@@ -0,0 +1,528 @@
use crate::{Identity, TypeCmp, TypeWitnessTypeArg, MakeTypeWitness};
use crate::const_marker::{ConstMarkerOf, ConstMarker};
/// For types whose values have a [`ConstMarker`] equivalent.
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_83")))]
pub trait HasConstMarker {
/// The type witness used by the [`ConstMarkerEq<Of = Self>`](ConstMarkerEq) impl of `CM`
///
/// Implementations that don't need to use a type witness can use
/// ```rust
/// # use typewit::const_marker::ConstMarkerOf;
/// # struct X;
/// # impl typewit::const_marker::HasConstMarker for X {
/// type Witness<CM: ConstMarkerOf<Self>> = typewit::TypeEq<CM, CM>;
/// # }
/// ```
type Witness<CM: ConstMarkerOf<Self>>: TypeWitnessTypeArg;
}
/// A [`ConstMarker`] that can be compared to another `ConstMarker` to
/// produce a [`TypeCmp`] of the comparison.
///
/// This trait is mostly designed to support `ConstMarker`s of:
/// - primitive std types
/// - field-less enums
///
/// # Examples
///
/// - [basic usage of std types](#basic-example)
/// - [defining type-level enums](#enum-example)
/// - [emulating const parameters whose type is generic](#generic-usage-example)
///
///
/// <div id="basic-example"> </div>
///
/// ### Basic usage of std types
///
/// ```rust
/// use typewit::TypeCmp;
/// use typewit::const_marker::{ConstMarker, ConstMarkerEqOf, U8};
///
///
/// const _: () = {
/// // T == U
/// assert!(matches!(typecast::<_, U8<5>>(U8::<5>), Ok(U8::<5>)));
///
/// // T != U
/// assert!(matches!(typecast::<_, U8<5>>(U8::<3>), Err(U8::<3>)));
/// assert!(matches!(typecast::<_, U8<5>>(U8::<4>), Err(U8::<4>)));
/// assert!(matches!(typecast::<_, U8<5>>(U8::<6>), Err(U8::<6>)));
/// assert!(matches!(typecast::<_, U8<5>>(U8::<7>), Err(U8::<7>)));
/// };
///
///
/// // Typecasts `T` to `U` if T == U, returns `Err(val)` if `T != U`.
/// const fn typecast<T, U>(val: T) -> Result<U, T>
/// where
/// T: ConstMarkerEqOf<u8>,
/// U: ConstMarkerEqOf<u8>,
/// {
/// match T::Equals::<U>::VAL {
/// TypeCmp::Eq(te) => Ok(te.to_right(val)),
/// TypeCmp::Ne(_) => Err(val)
/// }
/// }
///
/// ```
///
/// <div id="enum-example"> </div>
///
/// ### Enum
///
/// Defining a type-level enum that can be compared for equality with `ConstMarkerEq`
///
/// ```rust
/// use typewit::TypeCmp;
/// use typewit::const_marker::{
/// ConstMarker, ConstMarkerOf, ConstMarkerEq, ConstMarkerEqOf, HasConstMarker
/// };
///
/// const _: () = {
/// // returns Some if L == R
/// assert!(matches!(typecast_bar::<_, _, First>(&Bar(3, First)), Some(&Bar(3, First))));
/// assert!(matches!(typecast_bar::<_, _, Second>(&Bar(5, Second)), Some(&Bar(5, Second))));
/// assert!(matches!(typecast_bar::<_, _, Third>(&Bar(8, Third)), Some(&Bar(8, Third))));
///
/// // returns None if L != R
/// assert!(matches!(typecast_bar::<_, _, First>(&Bar(5, Second)), None));
/// assert!(matches!(typecast_bar::<_, _, First>(&Bar(8, Third)), None));
///
/// assert!(matches!(typecast_bar::<_, _, Second>(&Bar(3, First)), None));
/// assert!(matches!(typecast_bar::<_, _, Second>(&Bar(8, Third)), None));
///
/// assert!(matches!(typecast_bar::<_, _, Third>(&Bar(3, First)), None));
/// assert!(matches!(typecast_bar::<_, _, Third>(&Bar(5, Second)), None));
/// };
///
///
/// // Typecasts `&Bar<T, L>` to `&Bar<T, R>` if L == R, returns `None` if `L != R`.
/// const fn typecast_bar<T, L, R>(bar: &Bar<T, L>) -> Option<&Bar<T, R>>
/// where
/// L: ConstMarkerEqOf<Order>,
/// R: ConstMarkerEqOf<Order>,
/// {
/// // type-level function (TypeFn implementor) from `X` to `Bar<T, X>`
/// typewit::type_fn!{
/// struct BarFn<T>;
/// impl<X> X => Bar<T, X>
/// }
///
/// match L::Equals::<R>::VAL {
/// // te: TypeEq<L, R>, a proof of L == R
/// // .map(BarFn::NEW): TypeEq<Bar<T, L>, Bar<T, R>>
/// // .in_ref(): TypeEq<&Bar<T, L>, &Bar<T, R>>
/// TypeCmp::Eq(te) => Some(te.map(BarFn::NEW).in_ref().to_right(bar)),
/// TypeCmp::Ne(_) => None,
/// }
/// }
///
///
/// struct Bar<T, L>(T, L);
///
/// // Order enum and type-level enum
///
/// enum Order {
/// First = 1,
/// Second,
/// Third,
/// }
///
/// impl HasConstMarker for Order {
/// // the type witness of the `ConstMarkerEq` implementors below
/// type Witness<T: ConstMarkerOf<Self>> = OrderWit<T>;
/// }
///
/// typewit::simple_type_witness! {
/// // Declares `enum OrderWit<__Wit>`
/// // (the `__Wit` type parameter is implicitly added after all generics),
/// // the `Equals` derive adds this inherent method:
/// // ```rust
/// // const fn equals<Wit2>(self, rhs: OrderWit<Wit2>) -> TypeCmp<__Wit, Wit2>
/// // ```
/// derive(Equals)
/// enum OrderWit {
/// First = First,
/// Second = Second,
/// Third = Third,
/// }
/// }
///
/// macro_rules! declare_type_level_variant {($variant:ident) => {
/// struct $variant;
///
/// impl ConstMarker for $variant {
/// type Of = Order;
/// const VAL: Self::Of = Order::$variant;
/// }
///
/// impl ConstMarkerEq for $variant {
/// type Equals<Rhs: ConstMarkerEqOf<Self::Of>> = OrderTypeEquals<Self, Rhs>;
/// }
/// }}
///
/// declare_type_level_variant!{First}
/// declare_type_level_variant!{Second}
/// declare_type_level_variant!{Third}
///
/// // Emulates a generic constant for `ConstMarkerEq::Equals` above
/// // by implementing `ConstMarker` below.
/// struct OrderTypeEquals<L, R>(core::marker::PhantomData<(L, R)>);
///
/// impl<L, R> ConstMarker for OrderTypeEquals<L, R>
/// where
/// L: ConstMarkerEqOf<Order>,
/// R: ConstMarkerEqOf<Order>,
/// {
/// type Of = typewit::TypeCmp<L, R>;
/// const VAL: Self::Of = {
/// // `CM_WITNESS` comes from the `ConstMarkerHasWitness` supertrait of `ConstMarkerEq`
/// let lhs_wit: OrderWit<L> = L::CM_WITNESS;
/// let rhs_wit: OrderWit<R> = R::CM_WITNESS;
/// lhs_wit.equals(rhs_wit)
/// };
/// }
/// ```
///
/// <div id="generic-usage-example"> </div>
///
/// ### Generic usage
///
/// This example demonstrates emulation of const parameters of generic type
/// (as in, it emulates a `struct Pair<Of, const T: Of, const U: Of>;` type)
///
/// ```rust
/// use typewit::{Identity, TypeCmp, TypeEq};
/// use typewit::const_marker::{
/// CmEquals, ConstMarker, ConstMarkerOf, ConstMarkerEq, ConstMarkerEqOf, HasConstMarker,
/// I8, I16, U8, U16,
/// };
///
/// use core::marker::PhantomData as PD;
///
/// const _: () = {
/// // `T == U`, does the typecast
/// assert!(matches!(
/// typecast::<Pair<U8<3>, U8<5>>, Pair<U8<3>, U8<5>>>(Pair(PD)),
/// Ok(Pair::<U8<3>, U8<5>>(PD)),
/// ));
/// assert!(matches!(
/// typecast::<Pair<I8<3>, I8<5>>, Pair<I8<3>, I8<5>>>(Pair(PD)),
/// Ok(Pair::<I8<3>, I8<5>>(PD)),
/// ));
///
/// // `T != U`, returns error
/// assert!(matches!(
/// typecast::<Pair<U16<3>, U16<5>>, Pair<U16<3>, U16<9>>>(Pair(PD)),
/// Err(Pair::<U16<3>, U16<5>>(PD)),
/// ));
/// assert!(matches!(
/// typecast::<Pair<I16<3>, I16<5>>, Pair<I16<9>, I16<5>>>(Pair(PD)),
/// Err(Pair::<I16<3>, I16<5>>(PD)),
/// ));
/// };
///
/// // Typecasts `T` to `U` if `T == U`, returns `Err(pair)` if `T != U`.
/// const fn typecast<T: IsPair, U: IsPair<Of = T::Of>>(pair: T) -> Result<U, T> {
/// match T::PairEquals::<U>::VAL {
/// // `te: TypeEq<T, U>`, a proof of `T == U`
/// TypeCmp::Eq(te) => Ok(te.to_right(pair)),
/// TypeCmp::Ne(_) => Err(pair),
/// }
/// }
///
/// #[derive(Copy, Clone)]
/// struct Pair<T, U>(PD<(T, U)>);
///
/// // Trait for Pair
/// //
/// // this Identity supertrait emulates a `P == Pair<P::T, P::U>` constraint,
/// // it then allows coercing `P` to `Pair` and vice-versa.
/// trait IsPair: Identity<Type = Pair<Self::T, Self::U>> + Copy {
/// // The type of the constants that the `ConstMarker` parameters emulate.
/// type Of;
///
/// // The first type parameter of `Pair`
/// type T: ConstMarkerEqOf<Self::Of>;
///
/// // The second type parameter of `Pair`
/// type U: ConstMarkerEqOf<Self::Of>;
///
/// // `ConstMarker` that compares `Self` and `Rhs` for equality,
/// // producing a `TypeCmp<Self, Rhs>` of their (in)equality
/// type PairEquals<Rhs: IsPair<Of = Self::Of>>: ConstMarkerOf<TypeCmp<Self, Rhs>>;
/// }
///
/// impl<T, U> IsPair for Pair<T, U>
/// where
/// T: ConstMarkerEq + Copy,
/// U: ConstMarkerEqOf<T::Of> + Copy,
/// {
/// type Of = T::Of;
/// type T = T;
/// type U = U;
/// type PairEquals<Rhs: IsPair<Of = T::Of>> = PairEquals<Self, Rhs>;
/// }
///
/// struct PairEquals<Lhs, Rhs>(core::marker::PhantomData<(Lhs, Rhs)>);
///
/// impl<Lhs, Rhs> ConstMarker for PairEquals<Lhs, Rhs>
/// where
/// Lhs: IsPair,
/// Rhs: IsPair<Of = Lhs::Of>,
/// {
/// type Of = TypeCmp<Lhs, Rhs>;
/// const VAL: Self::Of = {
/// // type-level function (InjTypeFn implementor) from (T, U) to Pair<T, U>
/// // need `inj_type_fn` to map a `TypeCmp` (`typewit::type_fn` doesn't work)
/// typewit::inj_type_fn! {
/// struct PairFn;
/// impl<T, U> (T, U) => Pair<T, U>
/// }
///
/// // uses the `Identity` supertrait to get a proof that `Lhs` and `Rhs` are `Pair`s
/// let eq_lhs: TypeEq<Lhs, Pair<Lhs::T, Lhs::U>> = Lhs::TYPE_EQ;
/// let eq_rhs: TypeEq<Rhs, Pair<Rhs::T, Rhs::U>> = Rhs::TYPE_EQ;
///
/// let cmp_t: TypeCmp<Lhs::T, Rhs::T> = CmEquals::<Lhs::T, Rhs::T>::VAL;
/// let cmp_u: TypeCmp<Lhs::U, Rhs::U> = CmEquals::<Lhs::U, Rhs::U>::VAL;
///
/// let cmp: TypeCmp<Pair<Lhs::T, Lhs::U>, Pair<Rhs::T, Rhs::U>> =
/// cmp_t.zip(cmp_u).map(PairFn::NEW);
///
/// cmp.join_left(eq_lhs).join_right(eq_rhs.flip())
/// };
/// }
///
/// ```
///
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_83")))]
pub trait ConstMarkerEq: ConstMarker + ConstMarkerHasWitness {
/// [`ConstMarker`] for getting whether `Self` and `Rhs` are the same type.
///
/// If you need to write `<T as ConstMarkerEq>::Equals::<U>` for diambiguation
/// (instead of `T::Equals::<U>`),
/// consider using [`CmEquals`] instead.
///
/// (ideally this would be a generic associated constant, but those are unstable)
type Equals<Rhs: ConstMarkerEq<Of = Self::Of>>:
ConstMarkerOf<TypeCmp<Self, Rhs>>;
}
/// Trait alias for `ConstMarkerEq<Of = Of>`
///
/// This trait also shows the `Of` type in unsatisfied trait bound errors
/// (`ConstMarkerEq<Of = ...>` bounds obfuscate this a bit as of 1.89.0)
#[diagnostic::on_unimplemented(
message = "`{Self}` is not a comparable type-level constant of type `{Of}`",
)]
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_83")))]
pub trait ConstMarkerEqOf<Of>: ConstMarkerEq<Of = Of> {}
impl<C, Of> ConstMarkerEqOf<Of> for C
where
C: ConstMarkerEq<Of = Of>,
{}
/// For getting the type witness of this `ConstMarker`.
///
/// The witness type is determined by the [`Self::Of::Witness`](HasConstMarker::Witness)
/// associated type, not `Self` directly.
/// This allows multiple types with the same `Of` associated type to
/// have a compatible witness.
///
/// For std types, this doesn't produce anything useful,
/// this is mostly intended for user-defined types to be able to use their
/// type witness in the `ConstMarkerOf<TypeCmp<Lhs, Rhs>>` impl of the
/// [`ConstMarkerEq::Equals`] associated type.
///
///
/// Note: this trait is blanket implemented and cannot be manually implemented.
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_83")))]
pub trait ConstMarkerHasWitness: ConstMarker<Of: HasConstMarker> {
/// The type witness of this `ConstMarker`
///
const CM_WITNESS: <Self::Of as HasConstMarker>::Witness<Self>;
#[doc(hidden)]
type __Seal__: MakeTypeWitness + Identity<Type = <Self::Of as HasConstMarker>::Witness<Self>>;
}
impl<CM> ConstMarkerHasWitness for CM
where
CM: ConstMarker,
CM::Of: HasConstMarker<Witness<CM>: MakeTypeWitness>,
{
const CM_WITNESS: <Self::Of as HasConstMarker>::Witness<Self> = MakeTypeWitness::MAKE;
#[doc(hidden)]
type __Seal__ = <Self::Of as HasConstMarker>::Witness<Self>;
}
////////////////////////////////////////////////////////////////////////////////
/// Type alias for [`<Lhs as ConstMarkerEq>::Equals::<Rhs>`](ConstMarkerEq::Equals),
/// a [`ConstMarker<Of = TypeCmp<Lhs, Rhs>>`](ConstMarker).
///
/// This alias is useful to avoid the verbosity of using
/// `<Lhs as ConstMarkerEq>::Equals::<Rhs>` for diambiguation
/// (whenever `Lhs::Equals::<Rhs>` is ambiguous),
///
/// # Example
///
/// ```rust
/// use typewit::TypeCmp;
/// use typewit::const_marker::{CmEquals, ConstMarker, U8};
///
/// // U8<3> != U8<5>
/// assert!(matches!(CmEquals::<U8<3>, U8<5>>::VAL, TypeCmp::<U8<3>, U8<5>>::Ne(_)));
///
/// // U8<3> == U8<5>
/// assert!(matches!(CmEquals::<U8<5>, U8<5>>::VAL, TypeCmp::<U8<5>, U8<5>>::Eq(_)));
/// ```
///
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_83")))]
pub type CmEquals<Lhs, Rhs> =
<Lhs as ConstMarkerEq>::Equals::<Rhs>;
////////////////////////////////////////////////////////////////////////////////
/// Compared any two [`ConstMarkerEq`] types that have constants of the same type,
/// returning a proof of their type (in)equality.
///
/// # Example
///
/// ```rust
/// use typewit::TypeCmp;
/// use typewit::const_marker::{self, ConstMarkerEq, Char, U8};
///
/// assert_eq!(typecast(Char::<' '>, Char::<' '>), Ok([Char::<' '>, Char::<' '>]));
/// assert_eq!(typecast(Char::<'X'>, Char::<'Y'>), Err((Char::<'X'>, Char::<'Y'>)));
///
/// assert_eq!(typecast(U8::<3>, U8::<3>), Ok([U8::<3>, U8::<3>]));
/// assert_eq!(typecast(U8::<5>, U8::<8>), Err((U8::<5>, U8::<8>)));
///
///
///
/// const fn typecast<L, R>(lhs: L, rhs: R) -> Result<[L; 2], (L, R)>
/// where
/// L: ConstMarkerEq,
/// R: ConstMarkerEq<Of = L::Of>,
/// {
/// match const_marker::equals(&lhs, &rhs) {
/// TypeCmp::Eq(te) => Ok([lhs, te.to_left(rhs)]),
/// TypeCmp::Ne(_) => Err((lhs, rhs))
/// }
/// }
///
/// ```
///
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_83")))]
pub const fn equals<L, R>(_lhs: &L, _rhs: &R) -> TypeCmp<L, R>
where
L: ConstMarkerEq,
R: ConstMarkerEq<Of = L::Of>,
{
L::Equals::<R>::VAL
}
////////////////////////////////////////////////////////////////////////////////
/// Dummy type whose only purpose is to make sure that
/// the ConstMarker impl for StdTypeEquality is sound.
#[doc(hidden)]
pub struct __StdIdentityTypeEq<T>(pub(crate) core::marker::PhantomData<T>);
impl<T> crate::TypeWitnessTypeArg for __StdIdentityTypeEq<T> {
type Arg = T;
}
/// [`ConstMarker`] for getting whether `L` and `R` (two `ConstMarkerOf<StdType>`)
/// are the same type or not.
///
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_83")))]
pub struct StdTypeEquality<StdType, L, R>(pub(crate) core::marker::PhantomData<(StdType, L, R)>);
macro_rules! __const_marker_impls {
(
$(#[$struct_docs:meta])*
$struct:ident($prim:ty)
$(
$(#[$eq_docs:meta])*
fn equals $(($L:ident, $R:ident) $comparator:block)?;
)?
) => {
// keep this specific to `$struct<T>`,
// making this generic violates the safety assumptions of StdTypeEquality::VAL.
impl<const T: $prim> crate::MakeTypeWitness
for crate::const_marker::__StdIdentityTypeEq<$struct<T>>
{
const MAKE: Self = crate::const_marker::__StdIdentityTypeEq{
0: core::marker::PhantomData
};
}
impl crate::const_marker::HasConstMarker for $prim {
type Witness<CM: crate::const_marker::ConstMarkerOf<Self>> =
crate::const_marker::__StdIdentityTypeEq<CM>;
}
impl<const VAL: $prim> crate::const_marker::ConstMarkerEq for $struct<VAL> {
type Equals<Rhs: crate::const_marker::ConstMarkerEqOf<Self::Of>> =
crate::const_marker::StdTypeEquality<$prim, Self, Rhs>;
}
impl<L, R> crate::const_marker::ConstMarker
for crate::const_marker::StdTypeEquality<$prim, L, R>
where
L: crate::const_marker::ConstMarkerEqOf<$prim>,
R: crate::const_marker::ConstMarkerEqOf<$prim>,
{
const VAL: Self::Of =
if crate::const_marker::__const_eq_with!(
L::VAL,
R::VAL
$($(, ($L, $R) $comparator)?)?
) {
// SAFETY: (boy, this is complicated)
// - both `L` and `R` impl `ConstMarkerOf<$prim>`,
// - `L::VAL == R::VAL` (both are std types with sensible Eq impls)
// - `$prim` requires the witness type for `L` and `R` to be
// `__StdIdentityTypeEq`
// - `ConstMarkerHasWitness` requires that witness to impl `MakeTypeWitness`,
// - `__StdIdentityTypeEq` only impls `MakeTypeWitness` for marker types
// of std types defined in typewit
// - there's <= 1 `ConstMarkerEqOf<X>` impls in typewit
// where `X` is some type from std
//
// therefore: `L == R`
unsafe {
crate::TypeEq::<L, R>::new_unchecked().to_cmp()
}
} else {
// SAFETY: `L != R` (both are std types with sensible Eq impls)
// therefore `L != R`
unsafe {
crate::TypeNe::<L, R>::new_unchecked().to_cmp()
}
};
type Of = crate::TypeCmp<L, R>;
}
}
} pub(crate) use __const_marker_impls;

View File

@@ -0,0 +1,72 @@
/// A type that represents a constant
///
/// # Example
///
/// Emulating generic associated constants on stable
///
/// (this example Requires Rust 1.65.0)
///
#[cfg_attr(not(feature = "rust_1_65"), doc = "```ignore")]
#[cfg_attr(feature = "rust_1_65", doc = "```rust")]
/// use typewit::const_marker::{ConstMarker, ConstMarkerOf};
///
///
/// assert_eq!(make_array::<u8>(), ([3], [3, 3, 3]));
///
/// assert_eq!(make_array::<&str>(), (["hi"], ["hi", "hi", "hi"]));
///
/// const fn make_array<T: MakeArray>() -> ([T; 1], [T; 3]) {
/// (T::Make::<1>::VAL, T::Make::<3>::VAL)
/// }
///
/// // `MakeArray` can make arrays of any length without writing a bound for each length!!
/// trait MakeArray: Sized {
/// // emulates `const Make<const N: usize>: [Self; N];` (a generic associated constant)
/// type Make<const N: usize>: ConstMarkerOf<[Self; N]>;
/// }
///
///
/// impl MakeArray for u8 {
/// type Make<const N: usize> = MakeArrayConst<Self, N>;
/// }
///
/// impl<'a> MakeArray for &'a str {
/// type Make<const N: usize> = MakeArrayConst<Self, N>;
/// }
///
/// struct MakeArrayConst<T, const N: usize>(core::marker::PhantomData<T>);
///
/// impl<const N: usize> ConstMarker for MakeArrayConst<u8, N> {
/// type Of = [u8; N];
/// const VAL: Self::Of = [3; N];
/// }
///
/// impl<'a, const N: usize> ConstMarker for MakeArrayConst<&'a str, N> {
/// type Of = [&'a str; N];
/// const VAL: Self::Of = ["hi"; N];
/// }
///
/// ```
///
pub trait ConstMarker: Sized {
/// The type of this constant
type Of;
/// The value of this constant
const VAL: Self::Of;
}
/// Trait alias for `ConstMarker<Of = Of>`
///
/// This trait also shows the `Of` type in unsatisfied trait bound errors
/// (`ConstMarker<Of = ...>` bounds obfuscate this a bit as of 1.89.0)
#[cfg_attr(feature = "rust_1_83", diagnostic::on_unimplemented(
message = "`{Self}` is not a type-level constant of type `{Of}`",
))]
pub trait ConstMarkerOf<Of>: ConstMarker<Of = Of> {}
impl<C, Of> ConstMarkerOf<Of> for C
where
C: ConstMarker<Of = Of>,
{}

View File

@@ -0,0 +1,181 @@
use crate::{
all_init_bytes::slice_as_bytes,
TypeEq,
TypeNe,
};
#[cfg(test)]
mod tests;
super::declare_const_param_type! {
/// # Example
///
/// Using this marker type to implement dispatching of fields by name.
///
/// ```rust
/// #![feature(adt_const_params)]
/// #![feature(unsized_const_params)]
///
/// use typewit::{const_marker::Str, MakeTypeWitness};
///
/// let value = Stuff {
/// foo: 3,
/// bar: "hello",
/// };
///
/// assert_eq!(value.get::<"foo">(), &3);
/// assert_eq!(value.get::<"bar">(), &"hello");
///
/// pub struct Stuff<'a> {
/// foo: u32,
/// bar: &'a str,
/// }
///
/// impl<'a> Stuff<'a> {
/// const fn get<const S: &'static str>(&self) -> &<Self as Field<S>>::Type
/// where
/// FieldWit<Str<S>>: MakeTypeWitness,
/// Self: Field<S>,
/// {
/// let func = FnFieldTy::<Self>::NEW;
///
/// match FieldWit::MAKE {
/// FieldWit::Foo(te) => te.map(func).in_ref().to_left(&self.foo),
/// FieldWit::Bar(te) => te.map(func).in_ref().to_left(&self.bar),
/// }
/// }
/// }
///
/// typewit::type_fn! {
/// struct FnFieldTy<Struct>;
///
/// impl<const S: &'static str> Str<S> => <Struct as Field<S>>::Type
/// where Struct: Field<S>
/// }
///
/// trait Field<const S: &'static str> {
/// type Type: ?Sized;
/// }
/// impl<'a> Field<"foo"> for Stuff<'a> {
/// type Type = u32;
/// }
/// impl<'a> Field<"bar"> for Stuff<'a> {
/// type Type = &'a str;
/// }
///
/// typewit::simple_type_witness! {
/// // the #[non_exhaustive] is necessary to be able to add fields to Stuff
/// #[non_exhaustive]
/// pub enum FieldWit {
/// Foo = Str<"foo">,
/// Bar = Str<"bar">,
/// }
/// }
///
/// ```
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "adt_const_marker")))]
Str(&'static str)
fn equals(l, r) { u8_slice_eq(l.as_bytes(), r.as_bytes()) };
}
super::declare_const_param_type! {
StrSlice(&'static [&'static str])
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "adt_const_marker")))]
fn equals(l, r) { str_slice_eq(l, r) };
}
super::declare_const_param_type! {
BoolSlice(&'static [bool])
fn equals(l, r) { u8_slice_eq(slice_as_bytes(l), slice_as_bytes(r)) };
}
super::declare_const_param_type! {
CharSlice(&'static [char])
fn equals(l, r) { u8_slice_eq(slice_as_bytes(l), slice_as_bytes(r)) };
}
super::declare_const_param_type! {
U8Slice(&'static [u8])
fn equals(l, r) { u8_slice_eq(slice_as_bytes(l), slice_as_bytes(r)) };
}
super::declare_const_param_type! {
U16Slice(&'static [u16])
fn equals(l, r) { u8_slice_eq(slice_as_bytes(l), slice_as_bytes(r)) };
}
super::declare_const_param_type! {
U32Slice(&'static [u32])
fn equals(l, r) { u8_slice_eq(slice_as_bytes(l), slice_as_bytes(r)) };
}
super::declare_const_param_type! {
U64Slice(&'static [u64])
fn equals(l, r) { u8_slice_eq(slice_as_bytes(l), slice_as_bytes(r)) };
}
super::declare_const_param_type! {
U128Slice(&'static [u128])
fn equals(l, r) { u8_slice_eq(slice_as_bytes(l), slice_as_bytes(r)) };
}
super::declare_const_param_type! {
UsizeSlice(&'static [usize])
fn equals(l, r) { u8_slice_eq(slice_as_bytes(l), slice_as_bytes(r)) };
}
super::declare_const_param_type! {
I8Slice(&'static [i8])
fn equals(l, r) { u8_slice_eq(slice_as_bytes(l), slice_as_bytes(r)) };
}
super::declare_const_param_type! {
I16Slice(&'static [i16])
fn equals(l, r) { u8_slice_eq(slice_as_bytes(l), slice_as_bytes(r)) };
}
super::declare_const_param_type! {
I32Slice(&'static [i32])
fn equals(l, r) { u8_slice_eq(slice_as_bytes(l), slice_as_bytes(r)) };
}
super::declare_const_param_type! {
I64Slice(&'static [i64])
fn equals(l, r) { u8_slice_eq(slice_as_bytes(l), slice_as_bytes(r)) };
}
super::declare_const_param_type! {
I128Slice(&'static [i128])
fn equals(l, r) { u8_slice_eq(slice_as_bytes(l), slice_as_bytes(r)) };
}
super::declare_const_param_type! {
IsizeSlice(&'static [isize])
fn equals(l, r) { u8_slice_eq(slice_as_bytes(l), slice_as_bytes(r)) };
}
macro_rules! cmp_slice_of {
($left:ident, $right:ident, |$l:ident, $r:ident| $eq:expr) => {
if $left.len() != $right.len() {
false
} else {
let mut i = 0;
loop {
if i == $left.len() {
break true;
}
let $l = &$left[i];
let $r = &$right[i];
if !$eq {
break false;
}
i += 1;
}
}
}
}
const fn str_slice_eq(left: &[&str], right: &[&str]) -> bool {
cmp_slice_of!{left, right, |l, r| u8_slice_eq(l.as_bytes(), r.as_bytes())}
}
const fn u8_slice_eq(left: &[u8], right: &[u8]) -> bool {
cmp_slice_of!{left, right, |l, r| *l == *r}
}

View File

@@ -0,0 +1,42 @@
use super::{u8_slice_eq, str_slice_eq};
#[test]
fn u8_slice_test() {
assert!(u8_slice_eq(b"", b""));
assert!(!u8_slice_eq(b"", b"0"));
assert!(!u8_slice_eq(b"0", b""));
assert!(u8_slice_eq(b"0", b"0"));
assert!(!u8_slice_eq(b"0", b"1"));
assert!(!u8_slice_eq(b"1", b"0"));
assert!(!u8_slice_eq(b"0", b"0, 1"));
assert!(!u8_slice_eq(b"0, 1", b"0"));
assert!(!u8_slice_eq(b"0, 1", b"1"));
assert!(u8_slice_eq(b"0, 1", b"0, 1"));
assert!(!u8_slice_eq(b"0, 1", b"0, 2"));
}
#[test]
fn str_slice_eq_test() {
// different lengths
assert!(str_slice_eq(&[], &[]));
assert!(str_slice_eq(&[""], &[""]));
assert!(!str_slice_eq(&[], &[""]));
assert!(!str_slice_eq(&[""], &[]));
// length 1
assert!(str_slice_eq(&["foo"], &["foo"]));
assert!(!str_slice_eq(&["foo"], &["bar"]));
// length 2
assert!(str_slice_eq(&["foo", "bar"], &["foo", "bar"]));
assert!(!str_slice_eq(&["foo", "bar"], &["foo", "baz"]));
assert!(!str_slice_eq(&["foo", "bar"], &["foo", "bbr"]));
assert!(!str_slice_eq(&["foo", "bar"], &["foo", "car"]));
// length 3
assert!(str_slice_eq(&["foo", "foo2", "bar"], &["foo", "foo2", "bar"]));
assert!(!str_slice_eq(&["foo", "foo2", "bar"], &["foo", "foo2", "baz"]));
assert!(!str_slice_eq(&["foo", "foo2", "bar"], &["foo", "foo2", "bbr"]));
assert!(!str_slice_eq(&["foo", "foo2", "bar"], &["foo", "foo2", "car"]));
}

674
vendor/typewit/src/lib.rs vendored Normal file
View File

@@ -0,0 +1,674 @@
#![allow(clippy::needless_doctest_main)]
//! This crate provides abstractions for creating
//! [type witnesses](#what-are-type-witnesses).
//!
//! The inciting motivation for this crate is emulating trait polymorphism in `const fn`
//! (as of 2025-07-20, it's not possible to call trait methods in const contexts on stable).
//!
//! # What are type witnesses
//!
//! Type witnesses are values that prove the equality of a type parameter to a
//! fixed set of possible types.
//!
//! The simplest type witness is [`TypeEq<L, R>`][`TypeEq`],
//! which only proves equality of its `L` and `R` type parameters,
//! and can be used to coerce between them.
//!
//! Most type witnesses are enums with [`TypeEq`] fields,
//! which can coerce between a type parameter and as many types as there are variants.
//!
//! # Examples
//!
//! <span id="example0"></span>
//!
//! ### Polymorphic function
//!
//! This demonstrates how one can write a polymorphic `const fn`
//! (as of 2025-07-20, trait methods can't be called in const fns on stable)
//!
//! (this example requires Rust 1.61.0, since it uses trait bounds in const)
#![cfg_attr(not(feature = "rust_1_61"), doc = "```ignore")]
#![cfg_attr(feature = "rust_1_61", doc = "```rust")]
//! use typewit::{HasTypeWitness, TypeEq};
//!
//! const VALS: [&str; 6] = [
//! message(0),
//! message(1),
//! message(2),
//! message(3),
//! message("hi"),
//! message("foo"),
//! ];
//! assert_eq!(VALS, ["A", "B", "C", "A", "hi", "foo"]);
//!
//!
//! // A "method" of the `Message` trait (declared below)
//! const fn message<'a, T: Message<'a>>(val: T) -> &'a str {
//! match HasTypeWitness::WITNESS {
//! MessageWitness::Usize(te) => {
//! // `te` (a `TypeEq<T, usize>`) allows coercing between `T` and `usize`,
//! // because `TypeEq` is a value-level proof that both types are the same.
//! let index: usize = te.to_right(val);
//! ["A", "B", "C"][index % 3]
//! }
//! MessageWitness::Str(te) => {
//! // `te` is a `TypeEq<T, &'a str>`
//! te.to_right(val)
//! }
//! }
//! }
//!
//! // The trait that we use to emulate polymorphic dispatch,
//! // the limitation is that it can only emulate it for a limited set of types known
//! // to the crate that defines the trait, in this case that's `usize` and `&str`.
//! trait Message<'a>: HasTypeWitness<MessageWitness<'a, Self>> { }
//!
//! // replacing these impls with a blanket impl leads to worse compilation errors
//! impl<'a> Message<'a> for usize {}
//! impl<'a> Message<'a> for &'a str {}
//!
//! // This macro declares `enum MessageWitness<'a, __Wit>`, a type witness enum,
//! // where each variant requires and then guarantees `__Wit` to be a particular type.
//! // (the `__Wit` type parameter is implicitly added after all generics)
//! typewit::simple_type_witness! {
//! enum MessageWitness<'a> {
//! // This variant requires `__Wit == usize`
//! Usize = usize,
//!
//! // This variant requires `__Wit == &'a str`
//! Str = &'a str,
//! }
//! }
//! ```
//!
//! <span id="example-uses-type-fn"></span>
//! ### Indexing polymorphism
//!
//! This function demonstrates const fn polymorphism
//! and projecting [`TypeEq`] by implementing [`TypeFn`].
//!
//! (this example requires Rust 1.71.0, because it uses `<[T]>::split_at` in a const context.
#![cfg_attr(not(feature = "rust_stable"), doc = "```ignore")]
#![cfg_attr(feature = "rust_stable", doc = "```rust")]
//! use std::ops::Range;
//!
//! use typewit::{HasTypeWitness, TypeEq};
//!
//! fn main() {
//! let array = [3, 5, 8, 13, 21, 34, 55, 89];
//!
//! assert_eq!(index(&array, 0), &3);
//! assert_eq!(index(&array, 3), &13);
//! assert_eq!(index(&array, 0..4), [3, 5, 8, 13]);
//! assert_eq!(index(&array, 3..5), [13, 21]);
//! }
//!
//! const fn index<T, I>(slice: &[T], idx: I) -> &SliceIndexRet<I, T>
//! where
//! I: SliceIndex<T>,
//! {
//! // `I::WITNESS` is `<I as HasTypeWitness<IndexWitness<I>>>::WITNESS`,
//! match I::WITNESS {
//! IndexWitness::Usize(arg_te) => {
//! // `arg_te` (a `TypeEq<I, usize>`) allows coercing between `I` and `usize`,
//! // because `TypeEq` is a value-level proof that both types are the same.
//! let idx: usize = arg_te.to_right(idx);
//!
//! // using the `TypeFn` impl for `FnSliceIndexRet<T>` to
//! // map `TypeEq<I, usize>`
//! // to `TypeEq<SliceIndexRet<I, T>, SliceIndexRet<usize, T>>`
//! arg_te.project::<FnSliceIndexRet<T>>()
//! // converts`TypeEq<SliceIndexRet<I, T>, T>`
//! // to `TypeEq<&SliceIndexRet<I, T>, &T>`
//! .in_ref()
//! .to_left(&slice[idx])
//! }
//! IndexWitness::Range(arg_te) => {
//! let range: Range<usize> = arg_te.to_right(idx);
//! let ret: &[T] = slice_range(slice, range);
//! arg_te.project::<FnSliceIndexRet<T>>().in_ref().to_left(ret)
//! }
//! }
//! }
//!
//! // This macro declares a type witness enum
//! typewit::simple_type_witness! {
//! // Declares `enum IndexWitness<__Wit>`
//! // (the `__Wit` type parameter is implicitly added after all generics)
//! enum IndexWitness {
//! // This variant requires `__Wit == usize`
//! Usize = usize,
//!
//! // This variant requires `__Wit == Range<usize>`
//! Range = Range<usize>,
//! }
//! }
//!
//! /// Trait for all types that can be used as slice indices
//! ///
//! /// The `HasTypeWitness` supertrait allows getting a `IndexWitness<Self>`
//! /// with its `WITNESS` associated constant.
//! trait SliceIndex<T>: HasTypeWitness<IndexWitness<Self>> + Sized {
//! type Returns: ?Sized;
//! }
//! impl<T> SliceIndex<T> for usize {
//! type Returns = T;
//! }
//! impl<T> SliceIndex<T> for Range<usize> {
//! type Returns = [T];
//! }
//!
//! type SliceIndexRet<I, T> = <I as SliceIndex<T>>::Returns;
//!
//! // Declares `struct FnSliceIndexRet<T>`
//! // a type-level function (TypeFn implementor) from `I` to `SliceIndexRet<I, T>`
//! typewit::type_fn! {
//! struct FnSliceIndexRet<T>;
//!
//! impl<I: SliceIndex<T>> I => SliceIndexRet<I, T>
//! }
//!
//! const fn slice_range<T>(slice: &[T], range: Range<usize>) -> &[T] {
//! let suffix = slice.split_at(range.start).1;
//! suffix.split_at(range.end - range.start).0
//! }
//!
//! ```
//!
//! When the wrong type is passed for the index,
//! the compile-time error is the same as with normal generic functions:
//! ```text
//! error[E0277]: the trait bound `RangeFull: SliceIndex<{integer}>` is not satisfied
//! --> src/main.rs:43:30
//! |
//! 13 | assert_eq!(index(&array, ..), [13, 21]);
//! | ----- ^^ the trait `SliceIndex<{integer}>` is not implemented for `RangeFull`
//! | |
//! | required by a bound introduced by this call
//! |
//! = help: the following other types implement trait `SliceIndex<T>`:
//! std::ops::Range<usize>
//! usize
//! ```
//!
//! ### Downcasting const generic type
//!
//! This example demonstrates "downcasting" from a type with a const parameter to
//! a concrete instance of that type.
//!
//! ```rust
//! use typewit::{const_marker::Usize, TypeCmp, TypeEq};
//!
//! assert_eq!(*mutate(&mut Arr([])), Arr([]));
//! assert_eq!(*mutate(&mut Arr([1])), Arr([1]));
//! assert_eq!(*mutate(&mut Arr([1, 2])), Arr([1, 2]));
//! assert_eq!(*mutate(&mut Arr([1, 2, 3])), Arr([1, 3, 6])); // this is different!
//! assert_eq!(*mutate(&mut Arr([1, 2, 3, 4])), Arr([1, 2, 3, 4]));
//!
//! #[derive(Debug, PartialEq)]
//! struct Arr<const N: usize>([u8; N]);
//!
//! fn mutate<const N: usize>(arr: &mut Arr<N>) -> &mut Arr<N> {
//! if let TypeCmp::Eq(te) = Usize::<N>.equals(Usize::<3>) {
//! let tem = te // `te` is a `TypeEq<Usize<N>, Usize<3>>`
//! .project::<GArr>() // returns `TypeEq<Arr<N>, Arr<3>>`
//! .in_mut(); // returns `TypeEq<&mut Arr<N>, &mut Arr<3>>`
//!
//! // `tem.to_right(arr)` downcasts `arr` to `&mut Arr<3>`
//! tetra_sum(tem.to_right(arr));
//! }
//!
//! arr
//! }
//!
//! fn tetra_sum(arr: &mut Arr<3>) {
//! arr.0[1] += arr.0[0];
//! arr.0[2] += arr.0[1];
//! }
//!
//! // Declares `struct GArr`
//! // a type-level function (TypeFn implementor) from `Usize<N>` to `Arr<N>`
//! typewit::type_fn!{
//! struct GArr;
//!
//! impl<const N: usize> Usize<N> => Arr<N>
//! }
//! ```
//!
//! ### Builder
//!
//! Using a type witness to help encode a type-level enum,
//! and to match on that type-level enum inside of a function.
//!
//! The type-level enum is used to track the initialization of fields in a builder.
//!
//! This example requires Rust 1.65.0, because it uses Generic Associated Types.
#![cfg_attr(not(feature = "rust_1_65"), doc = "```ignore")]
#![cfg_attr(feature = "rust_1_65", doc = "```rust")]
//! use typewit::HasTypeWitness;
//!
//! fn main() {
//! // all default fields
//! assert_eq!(
//! StructBuilder::new().build(),
//! Struct{foo: "default value".into(), bar: vec![3, 5, 8]},
//! );
//!
//! // defaulted bar field
//! assert_eq!(
//! StructBuilder::new().foo("hello").build(),
//! Struct{foo: "hello".into(), bar: vec![3, 5, 8]},
//! );
//!
//! // defaulted foo field
//! assert_eq!(
//! StructBuilder::new().bar([13, 21, 34]).build(),
//! Struct{foo: "default value".into(), bar: vec![13, 21, 34]},
//! );
//!
//! // all initialized fields
//! assert_eq!(
//! StructBuilder::new().foo("world").bar([55, 89]).build(),
//! Struct{foo: "world".into(), bar: vec![55, 89]},
//! );
//! }
//!
//!
//! #[derive(Debug, PartialEq, Eq)]
//! struct Struct {
//! foo: String,
//! bar: Vec<u32>,
//! }
//!
//! struct StructBuilder<FooInit: InitState, BarInit: InitState> {
//! // If `FooInit` is `Uninit`, then this field is a `()`
//! // If `FooInit` is `Init`, then this field is a `String`
//! foo: BuilderField<FooInit, String>,
//!
//! // If `BarInit` is `Uninit`, then this field is a `()`
//! // If `BarInit` is `Init`, then this field is a `Vec<u32>`
//! bar: BuilderField<BarInit, Vec<u32>>,
//! }
//!
//! impl StructBuilder<Uninit, Uninit> {
//! pub const fn new() -> Self {
//! Self {
//! foo: (),
//! bar: (),
//! }
//! }
//! }
//!
//! impl<FooInit: InitState, BarInit: InitState> StructBuilder<FooInit, BarInit> {
//! /// Sets the `foo` field
//! pub fn foo(self, foo: impl Into<String>) -> StructBuilder<Init, BarInit> {
//! StructBuilder {
//! foo: foo.into(),
//! bar: self.bar,
//! }
//! }
//!
//! /// Sets the `bar` field
//! pub fn bar(self, bar: impl Into<Vec<u32>>) -> StructBuilder<FooInit, Init> {
//! StructBuilder {
//! foo: self.foo,
//! bar: bar.into(),
//! }
//! }
//!
//! /// Builds `Struct`,
//! /// providing default values for fields that haven't been set.
//! pub fn build(self) -> Struct {
//! Struct {
//! foo: init_or_else::<FooInit, _, _>(self.foo, || "default value".to_string()),
//! bar: init_or_else::<BarInit, _, _>(self.bar, || vec![3, 5, 8]),
//! }
//! }
//! }
//!
//! // Emulates a type-level `enum InitState { Init, Uninit }`
//! trait InitState: Sized + HasTypeWitness<InitWit<Self>> {
//! // How a builder represents an initialized/uninitialized field.
//! // If `Self` is `Uninit`, then this is `()`.
//! // If `Self` is `Init`, then this is `T`.
//! type BuilderField<T>;
//! }
//!
//! // If `I` is `Uninit`, then this evaluates to `()`
//! // If `I` is `Init`, then this evaluates to `T`
//! type BuilderField<I, T> = <I as InitState>::BuilderField::<T>;
//!
//! /// Gets `T` out of `maybe_init` if it's actually initialized,
//! /// otherwise returns `else_()`.
//! fn init_or_else<I, T, F>(maybe_init: BuilderField<I, T>, else_: F) -> T
//! where
//! I: InitState,
//! F: FnOnce() -> T
//! {
//! typewit::type_fn! {
//! // Declares the `HelperFn` type-level function (TypeFn implementor)
//! // from `I` to `BuilderField<I, T>`
//! struct HelperFn<T>;
//! impl<I: InitState> I => BuilderField<I, T>
//! }
//!
//! // matching on the type-level `InitState` enum by using `InitWit`.
//! // `WITNESS` comes from the `HasTypeWitness` trait
//! match I::WITNESS {
//! // `te: TypeEq<FooInit, Init>`
//! InitWit::InitW(te) => {
//! te.map(HelperFn::NEW) //: TypeEq<BuilderField<I, T>, T>
//! .to_right(maybe_init)
//! }
//! InitWit::UninitW(_) => else_(),
//! }
//! }
//!
//! // Emulates a type-level `InitState::Init` variant.
//! // Marks a field as initialized.
//! enum Init {}
//!
//! impl InitState for Init {
//! type BuilderField<T> = T;
//! }
//!
//! // Emulates a type-level `InitState::Uninit` variant.
//! // Marks a field as uninitialized.
//! enum Uninit {}
//!
//! impl InitState for Uninit {
//! type BuilderField<T> = ();
//! }
//!
//! typewit::simple_type_witness! {
//! // Declares `enum InitWit<__Wit>`, a type witness.
//! // (the `__Wit` type parameter is implicitly added after all generics)
//! enum InitWit {
//! // This variant requires `__Wit == Init`
//! InitW = Init,
//! // This variant requires `__Wit == Uninit`
//! UninitW = Uninit,
//! }
//! }
//! ```
//!
//! ### Generic Const Expressions
//!
//! This example uses [`Usize`] to coerce an arrays whose length is generic to
//! another generic, but equal, length.
//!
//! This example requires the `"generic_const_exprs"` crate feature because it uses the
//! currently-unstable [`generic_const_exprs`] language feature.
#![cfg_attr(not(feature = "generic_const_exprs"), doc = "```ignore")]
#![cfg_attr(feature = "generic_const_exprs", doc = "```rust")]
//! #![feature(generic_const_exprs)]
//!
//! use typewit::{const_marker::Usize, TypeCmp, TypeEq};
//!
//!
//! let mut arrays = Arrays::<1, 3> { a: [3, 5, 8], b: [13, 21, 34] };
//!
//! arrays.swap_inner();
//!
//! assert_eq!(arrays.a, [13, 21, 34]);
//! assert_eq!(arrays.b, [3, 5, 8]);
//!
//!
//! struct Arrays<const A: usize, const B: usize>
//! where
//! [u8; A * B]:,
//! [u8; B * A]:,
//! {
//! a: [u8; A * B],
//! b: [u8; B * A],
//! }
//!
//! impl<const A: usize, const B: usize> Arrays<A, B>
//! where
//! [u8; A * B]:,
//! [u8; B * A]:,
//! {
//! // Swaps the two array fields
//! const fn swap_inner(&mut self) {
//! let a = TypeEq::new::<u8>() // : TypeEq<u8, u8>
//! .in_array(commutative_proof::<A, B>()) // : TypeEq<[u8; A * B], [u8; B * A]>
//! .in_mut() // : TypeEq<&mut [u8; A * B], &mut [u8; B * A]>
//! .to_right(
//! &mut self.a // : &mut [u8; A * B]
//! ); // : &mut [u8; B * A]
//!
//! core::mem::swap(a, &mut self.b);
//! }
//! }
//!
//! const fn commutative_proof<const A: usize, const B: usize>(
//! ) -> TypeEq<Usize<{A * B}>, Usize<{B * A}>>
//! {
//! // panic-safety: A * B == B * A always holds, so this `unwrap_eq` can never panic
//! Usize::<{A * B}>.equals(Usize::<{B * A}>).unwrap_eq()
//! }
//!
//! ```
//!
//! If you tried to swap the fields directly, you'd get this error:
//! ```text
//! error[E0308]: mismatched types
//! --> src/lib.rs:437:38
//! |
//! 42 | core::mem::swap(&mut self.a, &mut self.b);
//! | ^^^^^^^^^^^ expected `A * B`, found `B * A`
//! |
//! = note: expected constant `A * B`
//! found constant `B * A`
//! ```
//!
//!
//! # Cargo features
//!
//! These are the features of this crate.
//!
//! ### Default-features
//!
//! These features are enabled by default:
//!
//! - `"proc_macros"`: uses proc macros to improve compile-errors involving
//! macro-generated impls.
//!
//! ### Rust-versions and standard crates
//!
//! These features enable items that have a minimum Rust version:
//!
//! - `"rust_stable"`: enables all the `"rust_1_*"` features.
//!
//! - `"rust_1_83"`: turns functions that take mutable references into `const fn`s,
//! enables [`const_marker`] items for comparing [`ConstMarker`]s,
//! and enables the `"rust_1_65"` feature.
//!
//! - `"rust_1_65"`: enables the [`type_constructors`] module,
//! the [`methods`] module,
//! and the `"rust_1_61"` feature.
//!
//! - `"rust_1_61"`: enables [`MetaBaseTypeWit`],
//! [`BaseTypeWitness`],
//! and the `{TypeCmp, TypeNe}::{zip*, in_array}` methods.
//!
//! These features enable items that require a non-`core` standard crate:
//!
//! - `"alloc"`: enable items that use anything from the standard `alloc` crate.
//!
//! ### Nightly features
//!
//! These features require the nightly Rust compiler:
//!
//! - `"adt_const_marker"`:
//! enables the `"rust_stable"` crate feature,
//! and marker types in the [`const_marker`] module that have
//! non-primitive `const` parameters.
//!
//! - `"generic_const_exprs"`:
//! enables the `"rust_stable"` crate feature,
//! and doc examples that use the [`generic_const_exprs`] unstable language feature.
//!
//! # No-std support
//!
//! `typewit` is `#![no_std]`, it can be used anywhere Rust can be used.
//!
//! You need to enable the `"alloc"` feature to enable items that use anything
//! from the standard `alloc` crate.
//!
//! # Minimum Supported Rust Version
//!
//! `typewit` supports Rust 1.57.0.
//!
//! Features that require newer versions of Rust, or the nightly compiler,
//! need to be explicitly enabled with crate features.
//!
//!
//!
//! [`TypeCmp`]: crate::TypeCmp
//! [`TypeEq`]: crate::TypeEq
//! [`TypeNe`]: crate::TypeNe
//! [`TypeFn`]: crate::type_fn::TypeFn
//! [`const_marker`]: crate::const_marker
//! [`type_constructors`]: crate::type_constructors
//! [`methods`]: crate::methods
//! [`MetaBaseTypeWit`]: crate::MetaBaseTypeWit
//! [`BaseTypeWitness`]: crate::BaseTypeWitness
//! [`Usize`]: crate::const_marker::Usize
//! [`typewit::const_marker`]: crate::const_marker
//! [`ConstMarker`]: crate::const_marker::ConstMarker
//! [`generic_const_exprs`]: https://doc.rust-lang.org/unstable-book/language-features/generic-const-exprs.html
#![no_std]
#![cfg_attr(feature = "adt_const_marker", feature(adt_const_params))]
#![cfg_attr(feature = "adt_const_marker", feature(unsized_const_params))]
#![cfg_attr(feature = "adt_const_marker", allow(incomplete_features))]
#![cfg_attr(feature = "docsrs", feature(doc_cfg))]
#![allow(clippy::type_complexity)]
#![deny(missing_docs)]
#![deny(clippy::missing_const_for_fn)]
#![deny(unused_results)]
#[cfg(feature = "alloc")]
extern crate alloc;
// Documentation for concepts not specific to any one item
macro_rules! explain_type_witness {
() => ("\
A [type witness](crate#what-are-type-witnesses) is \
an enum whose variants only have [`TypeEq`](crate::TypeEq) fields.
Each variant requires the enum's type parameter to be a specific type.
")
}
#[macro_use]
pub mod type_fn;
pub mod const_marker;
#[cfg(feature = "adt_const_marker")]
mod all_init_bytes;
mod utils;
mod macros;
#[cfg(feature = "rust_1_61")]
mod base_type_wit;
#[cfg(feature = "rust_1_61")]
pub use crate::base_type_wit::{BaseTypeWitness, MetaBaseTypeWit};
#[cfg(feature = "rust_1_65")]
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_65")))]
pub mod methods;
#[cfg(feature = "rust_1_61")]
pub(crate) mod some_type_arg_is_ne;
#[cfg(feature = "rust_1_61")]
pub(crate) use self::some_type_arg_is_ne::SomeTypeArgIsNe;
mod type_cmp;
mod type_eq;
mod type_eq_ne_guts;
mod type_identity;
mod type_ne_;
/// [`TypeNe`]-related items
pub mod type_ne {
pub use crate::type_ne_::{LeftArg, RightArg};
#[doc(no_inline)]
pub use crate::{TypeNe, type_ne};
}
mod type_witness_traits;
#[cfg(feature = "rust_1_65")]
pub mod type_constructors;
#[doc(inline)]
pub use crate::{
type_eq::*,
type_ne_::TypeNe,
type_witness_traits::*,
type_identity::Identity,
};
pub use crate::type_cmp::TypeCmp;
#[doc(no_inline)]
pub use crate::type_fn::{CallFn, CallInjFn, InjTypeFn, RevTypeFn, TypeFn, UncallFn};
#[cfg(feature = "proc_macros")]
#[doc(hidden)]
pub use typewit_proc_macros::__impl_with_span;
/// tests doc lints with `cargo doc --features="__test_doc_lints rust_stable"`
#[cfg(all(feature = "__test_doc_lints"))]
pub mod test_doc_lints;
#[doc(hidden)]
pub mod __ {
pub use core::{
clone::Clone,
cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering},
fmt::{Debug, Formatter, Result as FmtResult},
hash::{Hash, Hasher},
marker::{Copy, PhantomData},
mem::{ManuallyDrop, discriminant},
option::Option,
primitive::{bool, usize},
assert, compile_error, concat, stringify,
};
pub use crate::{
type_identity::Identity,
macros::{
generics_parsing::{
__parse_generic_args_with_defaults,
__parse_in_generics,
__parse_ty_bounds,
__parse_where_clause_for_item_inner,
__pg_cfg_expansion,
__pg_parsed_ty_bounds,
},
simple_type_witness_macro::__stw_parse_variants,
},
};
}
#[cfg(all(doctest, feature = "generic_const_exprs"))]
#[doc = include_str!("../README.md")]
pub struct ReadmeTest;

30
vendor/typewit/src/macros.rs vendored Normal file
View File

@@ -0,0 +1,30 @@
pub(crate) mod generics_parsing;
pub(crate) mod simple_type_witness_macro;
mod type_fn_macro;
mod inj_type_fn_macro;
mod polymatch;
mod type_ne_macro;
#[cfg(not(feature = "proc_macros"))]
#[doc(hidden)]
#[macro_export]
macro_rules! __impl_with_span {
(
$impl_span:tt
($($impl_attrs:tt)*)
($($impl_trait:tt)*)
($($impl_type:tt)*)
($($impl_where:tt)*)
($($impl_assoc_items:tt)*)
) => {
$($impl_attrs)*
impl $($impl_trait)* for $($impl_type)*
$($impl_where)*
{
$($impl_assoc_items)*
}
};
}

View File

@@ -0,0 +1,696 @@
// Generates a macro that takes a sequence of tokens with balanced `<` and `>` tokens
// and collects it until one of the additional rules decides
macro_rules! declare_generics_consuming_macro {(
$_:tt $gen_consuming_macro_:ident = $gen_consuming_macro:ident
$parsing_where:expr;
$($additional_rules:tt)*
) => {
#[doc(hidden)]
#[macro_export]
macro_rules! $gen_consuming_macro_ {
(
$fixed:tt
[$_($counter:tt)*]
[$_($prev:tt)*]
[< $_($rem:tt)*]
) => {
$crate::__::$gen_consuming_macro!{
$fixed
[1 $_($counter)*]
[$_($prev)* <]
[$_($rem)*]
}
};
(
$fixed:tt
[$_($counter:tt)*]
[$_($prev:tt)*]
[<< $_($rem:tt)*]
) => {
$crate::__::$gen_consuming_macro!{
$fixed
[1 1 $_($counter)*]
[$_($prev)* <<]
[$_($rem)*]
}
};
(
$fixed:tt
[$counter0:tt $_($counter:tt)*]
[$_($prev:tt)*]
[> $_($rem:tt)*]
) => {
$crate::__::$gen_consuming_macro!{
$fixed
[$_($counter)*]
[$_($prev)* >]
[$_($rem)*]
}
};
(
$fixed:tt
[$counter0:tt $_($counter:tt)*]
[$_($prev:tt)*]
[>> $_($rem:tt)*]
) => {
$crate::__::$gen_consuming_macro!{
$fixed
[$_($counter)*]
[$_($prev)* >]
[> $_($rem)*]
}
};
(
$fixed:tt
[$counter0:tt $_($counter:tt)*]
[$_($prev:tt)*]
[>== $_($rem:tt)*]
) => {
$crate::__::$gen_consuming_macro!{
$fixed
[$_($counter)*]
[$_($prev)* >]
[== $_($rem)*]
}
};
(
$fixed:tt
[$counter0:tt $_($counter:tt)*]
[$_($prev:tt)*]
[>= $_($rem:tt)*]
) => {
$crate::__::$gen_consuming_macro!{
$fixed
[$_($counter)*]
[$_($prev)* >]
[= $_($rem)*]
}
};
$($additional_rules)*
(
$fixed:tt
$counter:tt
[$_($prev:tt)*]
[$token:tt $_($rem:tt)*]
) => {
$crate::__::$gen_consuming_macro!{
$fixed
$counter
[$_($prev)* $token]
[$_($rem)*]
}
};
( $fixed:tt $counter:tt [$_($prev:tt)*] [$_($token0:tt $_($other:tt)*)?]) => {
$crate::__::compile_error!{$crate::__::concat!(
"unexpected end of ", $parsing_where,": `",
stringify!($_($prev)* $_($token0)?),
"`",
)}
};
( $_($other:tt)* ) => {
$crate::__::compile_error!{$crate::__::concat!(
"bug: unhandled syntax in `typewit` macro: ",
stringify!($_($other)*),
)}
};
}
pub use $gen_consuming_macro_ as $gen_consuming_macro;
}}
macro_rules! declare_parse_generics_macros {($_:tt [$($sep:tt)*] [$($err_token:tt)*]) => {
#[doc(hidden)]
#[macro_export]
macro_rules! __parse_in_generics_ {
$(
($fixed:tt $gen_args:tt $gen:tt [$_(,)? $err_token $_($rem:tt)*]) => {
$crate::__::compile_error!{$crate::__::concat!(
"unexpected `",
$crate::__::stringify!($err_token),
"` in generic parameter list",
)}
};
)*
(
( $_($callback:ident)::* !($_($callback_args:tt)*) )
// [$( (($($attrs)*) $generic_arg $phantom_arg = $default_val) )*]
// Example of a single parameter list:
// (() 'a (fn() -> &'a (),))
// (() T (fn() -> $crate::__::PhantomData<T>,))
// ((#[foo]) U (fn() -> $crate::__::PhantomData<U>,) = u32)
// (() N ())
// (() M () = 10)
$gen_args:tt
[$_(((/* no attributes */) $_($generics:tt)*))*]
[$_(,)* $_(> $_($rem:tt)*)?]
) => {
$_($callback)::* ! {
$_($callback_args)*
$gen_args
[$_(($_($generics)*))*]
[]
$_($_($rem)*)?
}
};
// if there is at least one generic param with cfg attributes
(
($_($fixed:tt)*)
$gen_args:tt
[$_((($_( $_(#[cfg($_($cfg:tt)+)])+ )?) $generics_first:tt $_($generics:tt)*))+]
[$_(,)* $_(> $_($rem:tt)*)?]
) => {
$crate::__::__pg_cfg_expansion!{
($_($fixed)* $_($_($rem)+)?)
[] $gen_args
[] [$_(($generics_first $_($generics)*))*]
[]
[$_( ($_($generics_first all( $_( $_($cfg)+ ),* ))?) )+]
}
};
(
($_($fixed:tt)*)
$gen_args:tt
[$_((($_(#[$_($attr:tt)*])*) $_($generics:tt)*))+]
[$_(,)* $_(> $_($rem:tt)*)?]
) => {
$_(
$crate::__assert_valid_gen_attr!{ [] [$_(#[$_($attr)*])*] }
)*
};
$(
(
$fixed:tt
[$_($prev_gen_args:tt)*]
[$_($prev_gen:tt)*]
[
$_(,)?
$_(#[$_($attr:tt)*])*
$lt:lifetime $_(:
$_($lt_bound0:lifetime $_( + $lt_bound1:lifetime)*)?
)?
$_($sep $_($rem:tt)*)?
]
) => {
$crate::__::__parse_in_generics!{
$fixed
[$_($prev_gen_args)* ($lt (fn() -> &$lt (),) )]
[
$_($prev_gen)*
(($_(#[$_($attr)*])*) $lt $_(: $_($lt_bound0 $_( + $lt_bound1 )* )?)?)
]
[$_($sep $_($rem)*)?]
}
};
(
$fixed:tt
[$_($prev_gen_args:tt)*]
[$_($prev_gen:tt)*]
[
$_(,)?
$_(#[$_($attr:tt)*])*
const $const:ident: $const_ty:ty $_(= $default:tt)?
$_($sep $_($rem:tt)*)?
]
) => {
$crate::__::__parse_in_generics!{
$fixed
[$_($prev_gen_args)* ($const () $_(= $default)?)]
[$_($prev_gen)* (($_(#[$_($attr)*])*) const $const: $const_ty)]
[$_($sep $_($rem)*)?]
}
};
)*
(
$fixed:tt
$prev_gen_args:tt
$prev_gen:tt
[
$_(,)? $_(#[$_($attr:tt)*])* $ty:ident: $_($rem:tt)*
]
) => {
$crate::__::__parse_ty_bounds!{
(
$fixed
$prev_gen_args
$prev_gen
($_(#[$_($attr)*])*)
$ty
)
[] // counter for depth between < > pairs
[]
[$_($rem)*]
}
};
(
$fixed:tt
$prev_gen_args:tt
$prev_gen:tt
[
$_(,)? $_(#[$_($attr:tt)*])* $ty:ident $_($rem:tt)*
]
) => {
$crate::__::__pg_parsed_ty_bounds!{
$fixed
$prev_gen_args
$prev_gen
($_(#[$_($attr)*])*)
$ty
[]
$_($rem)*
}
};
($fixed:tt $gen_args:tt $gen:tt []) => {
$crate::__::compile_error!{"unexpected end of generic parameter list"}
};
($fixed:tt $gen_args:tt $gen:tt [$token0:tt $_($token1:tt $_($other:tt)*)?]) => {
$crate::__::compile_error!{$crate::__::concat!(
"unexpected token(s) in generic parameter list: `",
stringify!($token0 $_($token1)?)
"`"
)}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __pg_parsed_ty_bounds_ {
$(
(
$fixed:tt $gen_args:tt $gen:tt $attrs:tt $ty:tt $bound:tt
[$err_token $_($rem:tt)*]
) => {
$crate::__::compile_error!{$crate::__::concat!(
"unexpected `",
$crate::__::stringify!($err_token),
"` in type parameter declaration",
)}
};
)*
$(
(
$fixed:tt
[$_($prev_gen_args:tt)*]
[$_($prev_gen:tt)*]
$attrs:tt
$ty:ident
[$_($_($bound:tt)+)?]
$_(= $default:ty)? $sep $_($rem:tt)*
) => {
$crate::__::__parse_in_generics!{
$fixed
[
$_($prev_gen_args)*
($ty (fn() -> $crate::__::PhantomData<$ty>,) $_(= $default)?)
]
[$_($prev_gen)* ($attrs $ty $_(: $_($bound)+)?)]
[$sep $_($rem)*]
}
};
)*
}
declare_generics_consuming_macro! {
$ __parse_ty_bounds_ = __parse_ty_bounds
"bound";
( ($_($fixed:tt)*) [] $prev:tt [$_(= $_($rem:tt)*)?] ) => {
$crate::__::__pg_parsed_ty_bounds!{ $_($fixed)* $prev $_(= $_($rem)*)? }
};
$(
( ($_($fixed:tt)*) [] $prev:tt [$sep $_($rem:tt)*] ) => {
$crate::__::__pg_parsed_ty_bounds!{ $_($fixed)* $prev $sep $_($rem)* }
};
)*
$(
($fixed:tt $count:tt [$_($prev:tt)*] [$err_token $_($rem:tt)*]) => {
$crate::__::compile_error!{$crate::__::concat!(
"unexpected end of bound: `",
stringify!($_($prev)* $err_token),
"`",
)}
};
)*
}
}}
declare_parse_generics_macros!{$ [, >] [; where impl]}
pub use {
__parse_in_generics_ as __parse_in_generics,
__pg_parsed_ty_bounds_ as __pg_parsed_ty_bounds,
};
macro_rules! declare_pg_cfg_expansion {
($_:tt
$(
[($deleted_lt_ty_marker_:ident) ($($gp_rule:tt)*) => {$($erase_marker_token:tt)*}]
)*
) => {
#[doc(hidden)]
#[macro_export]
macro_rules! __pg_cfg_expansion_ {
(
$fixed:tt
[$_($prev_gen_args:tt)*] [$gen_arg:tt $_($rem_gen_args:tt)*]
[$_($prev_generics:tt)*] [$generic:tt $_($rem_generics:tt)*]
$deleted_lt_ty_marker:tt
[() $_($rem_cfg:tt)*]
) => {
$crate::__::__pg_cfg_expansion!{
$fixed
[$_($prev_gen_args)* $gen_arg] [ $_($rem_gen_args)*]
[$_($prev_generics)* $generic] [ $_($rem_generics)*]
$deleted_lt_ty_marker
[$_($rem_cfg)*]
}
};
$(
(
$fixed:tt
[$_($prev_gen_args:tt)*] [$gen_arg:tt $_($rem_gen_args:tt)*]
[$_($prev_generics:tt)*] [$generic:tt $_($rem_generics:tt)*]
$_$deleted_lt_ty_marker_:tt
[($($gp_rule)* $_($cfg:tt)+) $_($rem_cfg:tt)*]
) => {
#[cfg($_($cfg)+)]
$crate::__::__pg_cfg_expansion!{
$fixed
[$_($prev_gen_args)* $gen_arg] [ $_($rem_gen_args)*]
[$_($prev_generics)* $generic] [ $_($rem_generics)*]
$_$deleted_lt_ty_marker_
[$_($rem_cfg)*]
}
#[cfg(not($_($cfg)+))]
$crate::__::__pg_cfg_expansion!{
$fixed
[$_($prev_gen_args)*] [ $_($rem_gen_args)*]
[$_($prev_generics)*] [ $_($rem_generics)*]
$($erase_marker_token)*
[$_($rem_cfg)*]
}
};
)*
(
( $_($callback:ident)::* !($_($callback_args:tt)*) $_($rem:tt)*)
$gen_args:tt []
$generics:tt []
$deleted_lt_ty_marker:tt
[] // no cfgs left
) => {
$_($callback)::* ! {
$_($callback_args)*
$gen_args
$generics
$deleted_lt_ty_marker
$_($rem)*
}
};
}
}}
declare_pg_cfg_expansion!{
$
[(deleted_lt_ty_marker) (const) => {$deleted_lt_ty_marker}]
[(deleted_lt_ty_marker) ($__gp:tt) => {[()]}]
}
pub use __pg_cfg_expansion_ as __pg_cfg_expansion;
#[doc(hidden)]
#[macro_export]
macro_rules! __parse_generics {
// angle bracket generics
(
$fixed:tt
[< $($generics:tt)*]
) => {
$crate::__::__parse_in_generics!{
$fixed
[]
[]
[$($generics)*]
}
};
// square bracket generic params
// note: this is accepted so that simple_type_witness
// can still parse square bracket generics.
(
$fixed:tt
[[$($generics:tt)*] $($rem:tt)*]
) => {
$crate::__::__parse_in_generics!{
$fixed
[]
[]
[$($generics)*> $($rem)*]
}
};
// no generics case
(
(
$($callback:ident)::* !($($callback_args:tt)*)
)
[$($rem:tt)*]
) => {
$($callback)::* ! {
$($callback_args)*
[]
[]
[]
$($rem)*
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __trailing_comma_for_where_clause {
// fallback case
(($($macro:ident)::* !($($args:tt)*)) [$($prev:tt)*] [] ) => {
$($macro)::* !{$($args)* [$($prev)*] }
};
(($($macro:ident)::* !($($args:tt)*)) [$($($prev:tt)+)?] [$(,)? ; $($rem:tt)*] ) => {
$($macro)::* !{$($args)* [$($($prev)+,)?] $($rem)* }
};
($fixed:tt [$($prev:tt)*] [$t0:tt $($rem:tt)*]) => {
$crate::__trailing_comma_for_where_clause!{
$fixed [$($prev)* $t0] [$($rem)*]
}
};
}
// parses a where clause for an item where the where clause ends at any of:
// - `=`
// - `{...}`
//
// The parsed tokens start with `where`, so that these can be parsed:
// - there being no where clause
// - having a normal where clause
// - having a where clause delimited with brackets (e.g: `where[T: u32]`)
#[doc(hidden)]
#[macro_export]
macro_rules! __parse_where_clause_for_item {
($fixed:tt where [$($in_brackets:tt)*]: $($rem:tt)*) => {
$crate::__::__parse_where_clause_for_item_inner!{
$fixed [] [] [[$($in_brackets)*]: $($rem)*]
}
};
// parses the `where [$where_predicates]` syntax that
// the simple_type_withness macro started with.
($fixed:tt where [$($in_brackets:tt)*] $($rem:tt)*) => {
$crate::__trailing_comma_for_where_clause!{
$fixed [] [$($in_brackets)*; $($rem)*]
}
};
($fixed:tt where $($rem:tt)*) => {
$crate::__::__parse_where_clause_for_item_inner!{
$fixed [] [] [$($rem)*]
}
};
// no where clause
(($($callback:ident)::* !($($callback_args:tt)*) ) $($rem:tt)*) => {
$($callback)::* !{$($callback_args)* [] $($rem)*}
};
}
declare_generics_consuming_macro! {
$ __parse_where_clause_for_item_inner_ = __parse_where_clause_for_item_inner
"where clause";
// forward compatibility with `const { ... }` bounds,
// dunno how likely const bounds are to be, but why not.
( $fixed:tt [] [$($prev:tt)*] [const {$($braced:tt)*} $($rem:tt)*] ) => {
$crate::__::__parse_where_clause_for_item!{
$fixed
[]
[$($prev)* const {$($braced)*}]
[$($rem)*]
}
};
(
($($callback:ident)::* !($($callback_args:tt)*) )
[]
[$($($prev:tt)+)?]
[$(,)? = $($rem:tt)*]
) => {
$($callback)::* !{$($callback_args)* [$($($prev)+,)?] = $($rem)*}
};
(
($($callback:ident)::* !($($callback_args:tt)*) )
[]
[$($($prev:tt)+)?]
[$(,)? {$($braced:tt)*} $($rem:tt)*]
) => {
$($callback)::* !{$($callback_args)* [$($($prev)+,)?] {$($braced)*} $($rem)*}
};
($fixed:tt [] $prev:tt []) => {
$crate::__::compile_error!{"unexpected end of where clause, expected rest of item"}
};
}
declare_generics_consuming_macro! {
$ __parse_generic_args_with_defaults_ = __parse_generic_args_with_defaults
"generic arguments";
(
($fixed:tt [$($prev_args:tt)*] [$($curr_gen_param:tt $($gen_params_rem:tt)*)?])
[]
[$($prev_tokens:tt)*]
[, $($rem:tt)*]
) => {
$crate::__::__parse_generic_args_with_defaults! {
($fixed [$($prev_args)* $($prev_tokens)*,] [$($($gen_params_rem)*)?])
[]
[]
[$($rem)*]
}
};
(
($fixed:tt [$($prev_args:tt)*] [$($curr_gen_param:tt $($gen_params_rem:tt)*)?])
[]
[$($prev_tokens:tt)+]
[> $($rem:tt)*]
) => {
$crate::__parse_generic_args_with_defaults__finish !{
($fixed [$($prev_args)* $($prev_tokens)*,] [$($($gen_params_rem)*)?])
$($rem)*
}
};
($fixed:tt [] [] [> $($rem:tt)*]) => {
$crate::__parse_generic_args_with_defaults__finish !{
$fixed $($rem)*
}
};
($fixed:tt [] $prev:tt []) => {
$crate::__::compile_error!{"unexpected end of generic arguments"}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __parse_generic_args_with_defaults__finish {
(
(
(
($($callback:ident)::* !($($callback_args:tt)*) )
$context:expr
)
[$($gen_args:tt)*]
[
$((
// gen_eff_def is either:
// - the default (if the generic parameter has one)
// - the name of the generic parameter (if it has no default)
(($($gen_eff_def:tt)*) $($__0:tt)*)
(
// defined if the generic parameter does not have a default
$([$gen_param:tt])?
// defined if the generic parameter has a default
$(($($__1:tt)*) [$__gen_param:tt])?
)
))*
]
)
$($rem:tt)*
) => {
$crate::__parse_generic_args_with_defaults__assert_only_defaults! {
$context,
[$($($gen_param)?)*]
}
$($callback)::* !{
$($callback_args)*
[$($gen_args)* $($($gen_eff_def)* ,)*]
$($rem)*
}
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! __parse_generic_args_with_defaults__assert_only_defaults {
(
$context:expr,
[$($($gen_param:tt)+)?]
) => {
$(
$crate::__::compile_error!{$crate::__::concat!{
"expected these generic argument(s) for ", $context, " to be passed: "
$( , stringify!($gen_param), )", "+
}}
)?
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __assert_valid_gen_attr {
( $prev:tt [#[cfg($($tt:tt)*)] $($rem:tt)*]) => {
$crate::__assert_valid_gen_attr!{ $prev [$($rem)*] }
};
( [$($prev:tt)*] [#[$($tt:tt)*] $($rem:tt)*]) => {
$crate::__assert_valid_gen_attr!{
[$($prev)* #[$($tt)*]]
[$($rem)*]
}
};
( [$(#[$attr:meta])*] []) => {
$crate::__::compile_error!{$crate::__::concat!{
"unsupported attribute(s) on generic parameter(s): "
$( ,"`#[", stringify!($attr), "]`", )", "*
"\nonly the `#[cfg(...)]` attribute is supported"
}}
};
}

View File

@@ -0,0 +1,182 @@
/// Declares an
/// [injective type-level function](crate::type_fn::InjTypeFn)
///
/// This macro takes in the exact same syntax as the [`type_fn`] macro.
///
/// This macro generates the same items as the `type_fn` macro,
/// in addition to implementing [`RevTypeFn`],
/// so that the function implements [`InjTypeFn`].
///
///
/// # Example
///
/// This macro is also demonstrated in
/// `TypeNe::{`[`map`]`, `[`project`]`, `[`unmap`]`, `[`unproject`]`}`.
///
/// [`map`]: crate::TypeNe::map
/// [`project`]: crate::TypeNe::project
/// [`unmap`]: crate::TypeNe::unmap
/// [`unproject`]: crate::TypeNe::unproject
///
/// ### Basic
///
/// ```rust
/// use typewit::{CallFn, UncallFn, inj_type_fn};
///
/// // Calls the `ToSigned` function with `u64` as the argument.
/// let _: CallFn<ToSigned, u64> = 3i64;
///
/// // Gets the argument of the `ToSigned` function from the `i8` return value.
/// let _: UncallFn<ToSigned, i8> = 5u8;
///
/// inj_type_fn!{
/// struct ToSigned;
///
/// impl u128 => i128;
/// impl u64 => i64;
/// impl u32 => i32;
/// impl u16 => i16;
/// impl u8 => i8;
/// }
/// ```
///
/// <details>
/// <summary>
/// <p>
///
/// the above `inj_type_fn` macro invocation roughly expands to this code
/// </p>
/// </summary>
///
/// ```rust
/// struct ToSigned;
///
/// impl ToSigned {
/// const NEW: Self = Self;
/// }
///
/// impl ::typewit::TypeFn<u128> for ToSigned {
/// type Output = i128;
/// }
///
/// impl ::typewit::RevTypeFn<i128> for ToSigned {
/// type Arg = u128;
/// }
///
/// impl ::typewit::TypeFn<u64> for ToSigned {
/// type Output = i64;
/// }
///
/// impl ::typewit::RevTypeFn<i64> for ToSigned {
/// type Arg = u64;
/// }
///
/// impl ::typewit::TypeFn<u32> for ToSigned {
/// type Output = i32;
/// }
///
/// impl ::typewit::RevTypeFn<i32> for ToSigned {
/// type Arg = u32;
/// }
///
/// impl ::typewit::TypeFn<u16> for ToSigned {
/// type Output = i16;
/// }
///
/// impl ::typewit::RevTypeFn<i16> for ToSigned {
/// type Arg = u16;
/// }
///
/// impl ::typewit::TypeFn<u8> for ToSigned {
/// type Output = i8;
/// }
///
/// impl ::typewit::RevTypeFn<i8> for ToSigned {
/// type Arg = u8;
/// }
/// ```
/// </details>
///
/// [`type_fn`]: macro@crate::type_fn
/// [`TypeFn`]: crate::type_fn::TypeFn
/// [`InjTypeFn`]: crate::type_fn::InjTypeFn
/// [`RevTypeFn`]: crate::type_fn::RevTypeFn
#[macro_export]
macro_rules! inj_type_fn {
($($args:tt)*) => {
$crate::__type_fn!{
__tyfn_injtypefn_impl
$($args)*
}
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! __tyfn_injtypefn_impl {
(
(
$(#[$attrs:meta])*
$impl:ident[$(($($fn_gen_param:tt)*))*] $ty_arg:ty => $ret_ty:ty
where[ $($where_preds:tt)* ]
)
$function_name:ident
[$(($capt_gen_args:tt $($rem_0:tt)*))*]
[
$(($capt_lt:lifetime $($capt_lt_rem:tt)*))*
$(($capt_tcp:ident $($capt_tcp_rem:tt)*))*
]
where [$($capt_where:tt)*]
) => {
$crate::__impl_with_span! {
$ty_arg // span
( $(#[$attrs])* #[allow(unused_parens)] )
(
<
$($capt_lt $($capt_lt_rem)*,)*
$($($fn_gen_param)*,)*
$($capt_tcp $($capt_tcp_rem)*,)*
> $crate::TypeFn<$ty_arg>
)
// for
( $function_name<$($capt_gen_args),*> )
(
where
$($capt_where)*
$($where_preds)*
)
(
type Output = $ret_ty;
const TYPE_FN_ASSERTS: () = { let _: $crate::CallInjFn<Self, $ty_arg>; };
)
}
$crate::__impl_with_span! {
$ret_ty // span
( $(#[$attrs])* #[allow(unused_parens)] )
(
<
$($capt_lt $($capt_lt_rem)*,)*
$($($fn_gen_param)*,)*
$($capt_tcp $($capt_tcp_rem)*,)*
> $crate::type_fn::RevTypeFn<$ret_ty>
)
// for
( $function_name<$($capt_gen_args),*> )
(
where
$($capt_where)*
$($where_preds)*
)
(
type Arg = $ty_arg;
)
}
};
}

223
vendor/typewit/src/macros/polymatch.rs vendored Normal file
View File

@@ -0,0 +1,223 @@
/// Match which expands top-level `|` patterns to multiple match arms.
///
/// [**examples below**](#examples)
///
/// ### Clarification
///
/// "top-level `|` patterns" means that the `|` is not inside some other pattern.
/// <br>E.g.: the pattern in `Foo(x) | Bar(x) => ` is a top-level `|` pattern.
/// <br>E.g.: the pattern in `(Foo(x) | Bar(x)) => ` is not a top-level `|` pattern,
/// because the `|` is inside parentheses.
///
/// # Syntax
///
/// This uses a `macro_rules!`-like syntax for the parameters of this macro
///
/// ```text
/// $matched_expression:expr;
/// $( $(|)? $($or_pattern:pat_param)|+ $(if $match_guard:expr)? => $arm_expr:expr ),*
/// $(,)?
/// ```
///
/// [**example demonstrating all of this syntax**](#full-syntax)
///
/// # Examples
///
/// ### Basic
///
/// ```rust
/// assert_eq!(debugify(Ok(3)), "3");
/// assert_eq!(debugify(Err("hello")), r#""hello""#);
///
/// fn debugify(res: Result<u32, &'static str>) -> String {
/// typewit::polymatch! {res;
/// Ok(x) | Err(x) => format!("{:?}", x)
/// }
/// }
/// ```
///
/// The above invocation of `polymatch` expands to:
///
/// ```rust
/// # assert_eq!(debugify(Ok(3)), "3");
/// # assert_eq!(debugify(Err("hello")), r#""hello""#);
/// #
/// # fn debugify(res: Result<u32, &'static str>) -> String {
/// match res {
/// Ok(x) => format!("{:?}", x),
/// Err(x) => format!("{:?}", x),
/// }
/// # }
/// ```
///
/// ### Full syntax
///
/// Example that uses all of the syntax supported by this macro.
///
/// ```rust
/// assert_eq!(bar(Foo::Byte(3)), 6);
/// assert_eq!(bar(Foo::Byte(9)), 18);
/// assert_eq!(bar(Foo::Byte(10)), 10);
///
/// assert_eq!(bar(Foo::U16(3)), 6);
/// assert_eq!(bar(Foo::U16(9)), 18);
/// assert_eq!(bar(Foo::U16(10)), 10);
///
/// assert_eq!(bar(Foo::U32(3)), 0);
///
/// assert_eq!(bar(Foo::Long(3)), 0);
///
/// enum Foo {
/// Byte(u8),
/// U16(u16),
/// U32(u32),
/// Long(u64),
/// }
///
/// const fn bar(foo: Foo) -> u64 {
/// typewit::polymatch! {foo;
/// // top-level `|` patterns generate a match arm for every alternate pattern
/// | Foo::Byte(x)
/// | Foo::U16(x)
/// if x < 10
/// => (x as u64) * 2,
///
/// Foo::Byte(x) | Foo::U16(x) => { x as u64 }
///
/// // `|` inside patterns behaves like in regular `match` expressions
/// (Foo::U32(_) | Foo::Long(_)) => 0
/// }
/// }
/// ```
///
/// The above invocation of `polymatch` expands to:
/// ```rust
/// # assert_eq!(bar(Foo::Byte(3)), 6);
/// # assert_eq!(bar(Foo::Byte(9)), 18);
/// # assert_eq!(bar(Foo::Byte(10)), 10);
/// #
/// # assert_eq!(bar(Foo::U16(3)), 6);
/// # assert_eq!(bar(Foo::U16(9)), 18);
/// # assert_eq!(bar(Foo::U16(10)), 10);
/// #
/// # assert_eq!(bar(Foo::U32(3)), 0);
/// #
/// # assert_eq!(bar(Foo::Long(3)), 0);
/// # enum Foo {
/// # Byte(u8),
/// # U16(u16),
/// # U32(u32),
/// # Long(u64),
/// # }
/// #
/// # const fn bar(foo: Foo) -> u64 {
/// match foo {
/// Foo::Byte(x) if x < 10 => (x as u64) * 2,
/// Foo::U16(x) if x < 10 => (x as u64) * 2,
///
/// Foo::Byte(x) => { x as u64 }
/// Foo::U16(x) => { x as u64 }
///
/// (Foo::U32(_) | Foo::Long(_)) => 0
/// }
/// # }
/// ```
///
#[macro_export]
macro_rules! polymatch {
($matching:expr; $($match_arms:tt)*) => {
$crate::__polymatch!{($matching) () $($match_arms)*}
};
($($tt:tt)*) => {
$crate::__::compile_error!{"expected arguments to be `matched expression; match arms`"}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __polymatch {
// Parsing match like syntax
(
($matching:expr)
( $( ($($pattern:tt)*) => ($expr:expr) )* )
// Nothing left to parse
$(,)?
) => {{
#[allow(unused_parens)]
match $matching {
$($($pattern)* => $expr,)*
}
}};
(
$fixed:tt
$prev_branch:tt
$(|)? $($pattern:pat_param)|+ $( if $guard:expr )? => $expr:expr
$(,$($rem:tt)*)?
) => {{
$crate::__polymatch__handle_guard!{
$fixed
$prev_branch
(($($pattern)+) => $expr)
($($guard)?)
($($($rem)*)?)
}
}};
(
$fixed:tt
$prev_branch:tt
$(|)? $($pattern:pat_param)|+ $( if $guard:expr )? => $expr:block
$($rem:tt)*
) => {{
$crate::__polymatch__handle_guard!{
$fixed
$prev_branch
(($($pattern)+) => $expr)
($($guard)?)
($($rem)*)
}
}};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __polymatch__handle_guard {
(
$fixed:tt
( $($prev_branch:tt)* )
(($($pattern:tt)+) => $expr:tt)
()
($($rem:tt)*)
) => {
$crate::__polymatch!{
$fixed
(
$($prev_branch)*
$(($pattern) => ($expr))*
)
$($rem)*
}
};
(
$fixed:tt
( $($prev_branch:tt)* )
(($($pattern:tt)+) => $expr:tt)
($guard:expr)
($($rem:tt)*)
) => {
$crate::__polymatch!{
$fixed
(
$($prev_branch)*
$(($pattern if $guard) => ($expr))*
)
$($rem)*
}
};
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,654 @@
/// Declares a type-level function (struct that implements [`TypeFn`](crate::TypeFn))
///
/// [**examples below**](#examples)
///
/// # Syntax
///
/// This section uses a `macro_rules!`-like syntax for
/// the parameters that `type_fn` takes
/// ```text
/// $(#[$attrs:meta])*
/// $vis:vis struct $struct_name:ident $(< $struct_generics:generic_params >)?
/// $( where $struct_where_predicates:where_predicates )?;
///
/// $(
/// $(#[$impl_attrs:meta])*
/// impl $(<$fn_generics:generic_params>)? $argument_type:ty => $return_type:ty
/// $( where $fn_where_predicates:where_predicates )?
/// );+
///
/// $(;)?
/// ```
///
/// `:where_predicates` is a sequence of constraints.
/// e.g: `T: Foo, 'a: 'b, U: 'b`.
///
/// `:generic_params` is a list of generic parameter declarations.
/// e.g: `'a, T, #[cfg(feature = "hi")] U, const N: usize`.
///
/// Generic parameters support the `#[cfg(...)]` attribute,
/// no other attribute is supported.
///
/// # Generated code
///
/// This macro generates:
///
/// - The struct declaration passed to the macro
///
/// - A `NEW` associated constant for constructing the struct
///
/// - Impls of [`TypeFn`] for the generated struct corresponding to
/// each `... => ...` argument.
///
/// If the struct has any lifetime or type parameters
/// (even if disabled by `#[cfg(...)]` attributes),
/// it has a private field,
/// and requires using its `NEW` associated constant to be instantiated.
/// If it has no type or lifetime parameters, the struct is a unit struct.
///
/// # Examples
///
/// This macro is also demonstrated in [`TypeEq::project`], [`TypeEq::map`],
/// and the [Indexing polymorphism](crate#example-uses-type-fn) root module example.
///
/// ### Basic
///
/// ```rust
/// use typewit::CallFn;
///
/// let item: CallFn<FnIterItem, Vec<&'static str>> = "hello";
/// let _: &'static str = item;
/// assert_eq!(item, "hello");
///
/// // Declares `struct FnIterItem`,
/// // a type-level function from `I` to `<I as IntoIterator>::Item`
/// typewit::type_fn!{
/// struct FnIterItem;
///
/// impl<I: IntoIterator> I => I::Item
/// }
/// ```
///
/// ### All syntax
///
/// Demonstrates all the syntax that this macro accepts and what it expands into:
///
#[cfg_attr(not(feature = "rust_1_61"), doc = "```ignore")]
#[cfg_attr(feature = "rust_1_61", doc = "```rust")]
/// typewit::type_fn! {
/// /// Hello
/// pub struct Foo<'a, T: IntoIterator = Vec<u8>, #[cfg(any())] const N: usize = 3>
/// where T: Clone;
///
/// /// docs for impl
/// #[cfg(all())]
/// impl<'b: 'a, U, #[cfg(all())] const M: usize>
/// [&'b U; M] => ([&'b U; M], T::IntoIter)
/// where
/// U: 'static,
/// u32: From<U>;
///
/// /// docs for another impl
/// impl () => T::Item
/// }
/// ```
/// the above macro invocation generates code equivalent to this:
#[cfg_attr(not(feature = "rust_1_61"), doc = "```ignore")]
#[cfg_attr(feature = "rust_1_61", doc = "```rust")]
/// use typewit::TypeFn;
///
/// use core::marker::PhantomData;
///
/// /// Hello
/// // The `const N: usize = 3` param is removed by the `#[cfg(any()))]` attribute
/// pub struct Foo<'a, T: IntoIterator = Vec<u8>>(
/// PhantomData<(&'a (), fn() -> T)>
/// ) where T: Clone;
///
/// impl<'a, T: IntoIterator> Foo<'a, T>
/// where
/// T: Clone,
/// {
/// pub const NEW: Self = Self(PhantomData);
/// }
///
/// /// docs for impl
/// #[cfg(all())]
/// impl<'a, 'b: 'a, U, T: IntoIterator, #[cfg(all())] const M: usize>
/// TypeFn<[&'b U; M]>
/// for Foo<'a, T>
/// where
/// T: Clone,
/// U: 'static,
/// u32: From<U>
/// {
/// type Output = ([&'b U; M], T::IntoIter);
/// }
///
/// /// docs for another impl
/// impl<'a, T: IntoIterator> TypeFn<()> for Foo<'a, T>
/// where
/// T: Clone,
/// {
/// type Output = T::Item;
/// }
///
/// ```
///
/// [`TypeFn`]: crate::TypeFn
/// [`TypeEq::project`]: crate::TypeEq::project
/// [`TypeEq::map`]: crate::TypeEq::map
#[macro_export]
macro_rules! type_fn {
($($args:tt)*) => {
$crate::__type_fn!{
__tyfn_typefn_impl
$($args)*
}
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! __type_fn {
(
$typefn_impl_callback:ident
$(#[$attrs:meta])*
$vis:vis struct $struct_name:ident < $($rem:tt)*
) => {
$crate::__::__parse_in_generics! {
($crate::__tyfn_parsed_capture_generics !((
$typefn_impl_callback
$(#[$attrs])*
$vis struct $struct_name
)))
[] [] [$($rem)*]
}
};
(
$typefn_impl_callback:ident
$(#[$attrs:meta])*
$vis:vis struct $struct_name:ident
$($rem:tt)*
) => {
$crate::__trailing_comma_for_where_clause!{
($crate::__tyfn_parsed_capture_where! (
(
$typefn_impl_callback
$(#[$attrs])*
$vis struct $struct_name [] [] []
)
))
[]
[$($rem)*]
}
};
($($rem:tt)*) => {
$crate::__::compile_error!{
"invalid argument for `type_fn` macro\n\
expected struct declaration followed by type-level function definitions"
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __tyfn_parsed_capture_generics {
(
($($struct_stuff:tt)*)
$capture_gen_args:tt
$capture_generics:tt
$deleted_markers:tt
where $($rem:tt)*
) => {
$crate::__trailing_comma_for_where_clause!{
($crate::__tyfn_parsed_capture_where! (
( $($struct_stuff)* $capture_gen_args $capture_generics $deleted_markers )
))
[]
[$($rem)*]
}
};
(
($($struct_stuff:tt)*)
$capture_gen_args:tt
$capture_generics:tt
$deleted_markers:tt
;$($rem:tt)*
) => {
$crate::__tyfn_parsed_capture_where! {
( $($struct_stuff)* $capture_gen_args $capture_generics $deleted_markers )
[]
$($rem)*
}
};
(
$struct_stuff:tt
$capture_gen_args:tt
$capture_generics:tt
$deleted_markers:tt
$($first_token:tt $($rem:tt)*)?
) => {
$crate::__::compile_error!{$crate::__::concat!(
"expected `;` after struct definition",
$( ", found `" $crate::__::stringify!($first_token), "`")?
)}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __tyfn_parsed_capture_where {
(
($($struct_stuff:tt)*)
$captures_where:tt
$($fns:tt)+
) => {
$crate::__tyfn_parse_fns! {
( $($struct_stuff)* captures_where $captures_where )
[]
[$($fns)*]
[$($fns)*]
}
};
(
($($struct_stuff:tt)*)
[impl $($fns:tt)*]
) => {
$crate::__::compile_error!{"expected `;` after struct declaration, found `impl`"}
};
(
$struct_stuff:tt
$where_predicates:tt
) => {
$crate::__::compile_error!{"expected at least one type-level function definition"}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __tyfn_parse_fns {
(
(
$typefn_impl_callback:ident
$(#[$attrs:meta])*
$vis:vis struct $struct_name:ident
$capture_gen_args:tt
$capture_generics:tt
$erased_lt_ty_marker:tt
captures_where $captures_where:tt
)
$fns:tt
[]
$rem_dup:tt // duplicate of the parsed tokens
) => {
$crate::__tyfn_split_capture_generics! {
$typefn_impl_callback
$fns
$(#[$attrs])*
$vis struct $struct_name
$capture_gen_args
$capture_gen_args
$capture_generics
$erased_lt_ty_marker
captures_where $captures_where
}
};
( $fixed:tt $fns:tt [] []) => {
$crate::__::compile_error!{$crate::__::concat!(
"bug: unhandled syntax in `typewit` macro: ",
stringify!($fixed),
stringify!($fns),
)}
};
(
$fixed:tt
$fns:tt
[
$(#[$impl_attrs:meta])*
impl < $($rem:tt)*
]
[ $(#[$_attr:meta])* $impl:ident $($rem_dup:tt)* ]
) => {
$crate::__::__parse_in_generics!{
($crate::__tyfn_parsed_fn_generics!(
$fixed
$fns
[$(#[$impl_attrs])* $impl]
))
[] [] [$($rem)*]
}
};
(
$fixed:tt
$fns:tt
[
$(#[$impl_attrs:meta])*
impl $($rem:tt)*
]
[ $(#[$_attr:meta])* $impl:ident $($rem_dup:tt)* ]
) => {
$crate::__tyfn_parsed_fn_generics!{
$fixed
$fns
[$(#[$impl_attrs])* $impl]
[] [] [] $($rem)*
}
};
(
$fixed:tt
$fns:tt
[
$(#[$impl_attrs:meta])*
impl $type_fn_arg:ty => $ret_ty:ty
where $($rem:tt)*
]
[ $(#[$_attr:meta])* $impl:ident $($rem_dup:tt)* ]
) => {
$crate::__trailing_comma_for_where_clause!{
($crate::__tyfn_parsed_fn_where!(
$fixed
$fns
[
$(#[$impl_attrs])*
$impl[] $type_fn_arg => $ret_ty
]
))
[]
[$($rem)*]
}
};
(
$fixed:tt
[$($fns:tt)*]
[
$(#[$impl_attrs:meta])*
impl $type_fn_arg:ty => $ret_ty:ty
$(; $($rem:tt)*)?
]
[ $(#[$_attr:meta])* $impl:ident $($rem_dup:tt)* ]
) => {
$crate::__tyfn_parse_fns!{
$fixed
[
$($fns)*
(
$(#[$impl_attrs])*
$impl[] $type_fn_arg => $ret_ty
where[]
)
]
[$($($rem)*)?]
[$($($rem)*)?]
}
};
(
$fixed:tt
$fns:tt
[
$(#[$impl_attrs:meta])*
$type_fn_arg:ty => $($rem:tt)*
]
$rem_dup:tt
) => {
$crate::__::compile_error!{$crate::__::concat!(
"expected `impl`, found `",
$crate::__::stringify!($type_fn_arg =>),
"`\n",
"helo: `impl ",
$crate::__::stringify!($type_fn_arg =>),
"` is likely to work."
)}
};
(
$fixed:tt
$fns:tt
[ $(#[$attrs:meta])* impl $arg:ty where $($rem:tt)* ]
$rem_dup:tt
) => {
$crate::__::compile_error!{"where clauses for functions go after the return type"}
};
( $fixed:tt [] [] [] ) => {
$crate::__::compile_error!{"expected type-level function definitions"}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __tyfn_parsed_fn_generics {
(
$fixed:tt
[$($fns:tt)*]
[$($prev_impl_tts:tt)*]
$__gen_args:tt
$gen_params:tt
$deleted_markers:tt
$type_fn_arg:ty => $ret_ty:ty
$(; $($rem:tt)*)?
) => {
$crate::__tyfn_parse_fns!{
$fixed
[
$($fns)*
(
$($prev_impl_tts)* $gen_params $type_fn_arg => $ret_ty
where[]
)
]
[$($($rem)*)?]
[$($($rem)*)?]
}
};
(
$fixed:tt
$fns:tt
[$($prev_impl_tts:tt)*]
$__gen_args:tt
$gen_params:tt
$deleted_markers:tt
$type_fn_arg:ty => $ret_ty:ty
where $($rem:tt)*
) => {
$crate::__trailing_comma_for_where_clause!{
($crate::__tyfn_parsed_fn_where!(
$fixed
$fns
[
$($prev_impl_tts)* $gen_params $type_fn_arg => $ret_ty
]
))
[]
[$($rem)*]
}
};
(
$fixed:tt
$fns:tt
$impl_attrs:tt
$__gen_args:tt
$gen_params:tt
$type_fn_arg:ty where $($rem:tt)*
) => {
$crate::__::compile_error!{"where clauses for functions go after the return type"}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __tyfn_parsed_fn_where {
(
$fixed:tt
[$($fns:tt)*]
[ $($fn_decl:tt)* ]
$where_preds:tt
$($rem:tt)*
) => {
$crate::__tyfn_parse_fns!{
$fixed
[ $($fns)* ( $($fn_decl)* where $where_preds ) ]
[$($rem)*]
[$($rem)*]
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __tyfn_split_capture_generics {
(
$typefn_impl_callback:ident
$functions:tt
$(#[$attrs:meta])*
$vis:vis struct $struct_name:ident
$capture_gen_args:tt
[$(($gen_arg:tt ($($($gen_phantom:tt)+)?) $($gen_rem:tt)*))*]
$capture_generics:tt
[$($erased_lt_ty_marker:tt)*]
captures_where $captures_where:tt
) => {
$crate::__tyfn_parsed!{
$typefn_impl_callback
$functions
$(#[$attrs])*
$vis struct $struct_name
$capture_gen_args
[$($(($($gen_phantom)+))?)* $(($erased_lt_ty_marker))*]
$capture_generics
$captures_where
}
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! __tyfn_parsed {
(
$typefn_impl_callback:ident
[$($functions:tt)+]
$(#[$attrs:meta])*
$vis:vis struct $function_name:ident
$capt_gen_args:tt
$capt_gen_phantom:tt
$capt_generics:tt
// where clause of the captures
$captures_where:tt
) => {
$crate::__tyfn_declare_struct!{
(
$(#[$attrs])*
$vis struct $function_name
)
$capt_gen_args
$capt_gen_phantom
$capt_generics
where $captures_where
}
$(
$crate::$typefn_impl_callback!{
$functions
$function_name
$capt_gen_args
$capt_generics
where $captures_where
}
)*
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! __tyfn_declare_struct {
(
(
$(#[$attrs:meta])*
$vis:vis struct $function_name:ident
)
[$(($gen_arg:tt $ignored:tt $(= $gen_default:tt)?))*]
[$($(@$has_phantom:tt)? $( ($($gen_phantom:tt)+) )+ )?]
[$(($($gen_params:tt)*))*]
where [$($($where:tt)+)?]
) => {
$(#[$attrs])*
$vis struct $function_name<$($($gen_params)* $(= $gen_default)?,)*> $((
$($has_phantom)?
$crate::__::PhantomData<($($($gen_phantom)*)*)>
))?
$(where $($where)+)?;
impl<$($($gen_params)*,)*> $function_name<$($gen_arg,)*>
$(where $($where)+)?
{
#[doc = $crate::__::concat!(
"Constructs a `", $crate::__::stringify!($function_name), "`"
)]
$vis const NEW: Self = Self $($($has_phantom)? ($crate::__::PhantomData))?;
}
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! __tyfn_typefn_impl {
(
(
$(#[$attrs:meta])*
$impl:ident[$(($($fn_gen_param:tt)*))*] $ty_arg:ty => $ret_ty:ty
where[ $($where_preds:tt)* ]
)
$function_name:ident
[$(($capt_gen_args:tt $($rem_0:tt)*))*]
[
$(($capt_lt:lifetime $($capt_lt_rem:tt)*))*
$(($capt_tcp:ident $($capt_tcp_rem:tt)*))*
]
where [$($capt_where:tt)*]
) => {
$crate::__impl_with_span! {
$ty_arg // span
( $(#[$attrs])* #[allow(unused_parens)] )
(
<
$($capt_lt $($capt_lt_rem)*,)*
$($($fn_gen_param)*,)*
$($capt_tcp $($capt_tcp_rem)*,)*
> $crate::TypeFn<$ty_arg>
)
// for
( $function_name<$($capt_gen_args),*> )
(
where
$($capt_where)*
$($where_preds)*
)
(
type Output = $ret_ty;
)
}
};
}

View File

@@ -0,0 +1,148 @@
/// Constructs a [`TypeNe`](crate::TypeNe)
/// of types that are statically known to be different.
///
/// This macro is syntactic sugar for calling
/// [`TypeNe::with_fn`](crate::TypeNe::with_fn) with a private
/// [`InjTypeFn`](crate::InjTypeFn) implementor.
///
/// # Syntax
///
/// This macro takes this syntax:
///
/// ```text
/// $( < $($generic_param:generic_param),* $(,)? > )? $left_type:ty, $right_type:ty
/// $(where $($where_cause:tt)*)?
/// ```
///
/// # Limitations
///
/// This macro can't use generic parameters from the surrounding scope,
/// they must be redeclared within the macro to be used.
///
/// # Example
///
/// ```rust
/// use typewit::TypeNe;
///
/// const _: TypeNe<u8, (u8,)> = foo();
///
/// const fn foo<T>() -> TypeNe<T, (T,)>
/// where
/// (T,): Copy,
/// {
/// typewit::type_ne!{
/// <X> X, (X,)
/// where (X,): Copy
/// }
/// }
///
///
/// ```
#[macro_export]
macro_rules! type_ne {
(< $($generics:tt)* ) => {
$crate::__::__parse_in_generics! {
($crate::__tyne_parsed_capture_generics !())
[] [] [$($generics)*]
}
};
($left_ty:ty, $($rem:tt)*) => {
$crate::__tyne_parsed_capture_generics! {
[]
[]
[]
$left_ty, $($rem)*
}
};
($($rem:tt)*) => {
$crate::__::compile_error!{"invalid arguments for `type_ne` macro"}
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! __tyne_parsed_capture_generics {
(
[$(($gen_arg:tt ($($($gen_phantom:tt)+)?) $($gen_rem:tt)*))*]
[$(($($gen_params:tt)*))*]
$deleted_markers:tt
$left_ty:ty, $right_ty:ty $(,)?
$(where $($where:tt)*)?
) => ({
struct __TypeNeParameterizer<$($($gen_params)*,)*>(
$crate::__::PhantomData<(
$($($crate::__::PhantomData<$($gen_phantom)+>,)?)*
)>
)$( where $($where)* )?;
impl<$($($gen_params)*,)*> __TypeNeParameterizer<$($gen_arg,)*>
$( where $($where)* )?
{
const NEW: Self = Self($crate::__::PhantomData);
}
$crate::__impl_with_span! {
$left_ty // span
() // impl attrs
( <$($($gen_params)*,)*> $crate::TypeFn<$crate::type_ne::LeftArg> )
// for
(__TypeNeParameterizer<$($gen_arg,)*>)
( $( where $($where)* )? )
(
type Output = $left_ty;
const TYPE_FN_ASSERTS: () = {
let _: $crate::CallInjFn<Self, $crate::type_ne::LeftArg>;
};
)
}
$crate::__impl_with_span! {
$left_ty // span
() // impl attrs
( <$($($gen_params)*,)*> $crate::RevTypeFn<$left_ty> )
// for
(__TypeNeParameterizer<$($gen_arg,)*>)
( $( where $($where)* )? )
(
type Arg = $crate::type_ne::LeftArg;
)
}
$crate::__impl_with_span! {
$right_ty // span
() // impl attrs
( <$($($gen_params)*,)*> $crate::TypeFn<$crate::type_ne::RightArg> )
// for
(__TypeNeParameterizer<$($gen_arg,)*>)
( $( where $($where)* )? )
(
type Output = $right_ty;
const TYPE_FN_ASSERTS: () = {
let _: $crate::CallInjFn<Self, $crate::type_ne::RightArg>;
};
)
}
$crate::__impl_with_span! {
$right_ty // span
() // impl attrs
( <$($($gen_params)*,)*> $crate::RevTypeFn<$right_ty> )
// for
(__TypeNeParameterizer<$($gen_arg,)*>)
( $( where $($where)* )? )
(
type Arg = $crate::type_ne::RightArg;
)
}
$crate::TypeNe::with_fn(
__TypeNeParameterizer::NEW
)
});
}

19
vendor/typewit/src/methods.rs vendored Normal file
View File

@@ -0,0 +1,19 @@
//! Generic versions of
//! [`TypeEq`](crate::TypeEq)/[`TypeNe`](crate::TypeNe)/[`TypeCmp`](crate::TypeCmp)
//! methods,
//! which can take any permutation of them as arguments.
mod zipping_;
/// For getting the return type of the zipping functions
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_65")))]
pub mod zipping {
pub use super::zipping_::{
Zip2, Zip3, Zip4,
Zip2Out, Zip3Out, Zip4Out,
};
}
pub use self::zipping_::{in_array, zip2, zip3, zip4};

525
vendor/typewit/src/methods/zipping_.rs vendored Normal file
View File

@@ -0,0 +1,525 @@
use crate::{
type_constructors::{
BaseTypeWitnessTc,
BaseTypeWitnessReparam,
MapBaseTypeWitness,
TcToBaseTypeWitness,
TcTypeCmp, TcTypeEq, TcTypeNe,
},
const_marker::Usize,
BaseTypeWitness,
MetaBaseTypeWit,
MetaBaseTypeWit as MBTW,
HasTypeWitness, SomeTypeArgIsNe,
TypeCmp, TypeEq, TypeNe
};
//////////////////////////////////////////////////////////////////////
macro_rules! return_type_docs {() => {concat!(
"# Return type\n",
"\n",
"The return type depends on the types of the arguments:\n",
"- if all arguments are [`TypeEq`], this returns a `TypeEq` \n",
"- if any argument is a [`TypeNe`], this returns a `TypeNe` \n",
"- if any argument is a [`TypeCmp`] and no argument is a `TypeNe`,",
" this returns a `TypeCmp` \n",
)}}
//////////////////////////////////////////////////////////////////////
#[doc(hidden)]
pub trait ZipTc: 'static + Copy {
type Output: BaseTypeWitnessTc;
}
#[doc(hidden)]
pub type ZipTcOut<TupleOfTc> = <TupleOfTc as ZipTc>::Output;
impl ZipTc for (TcTypeEq, TcTypeEq) {
type Output = TcTypeEq;
}
impl ZipTc for (TcTypeEq, TcTypeNe) {
type Output = TcTypeNe;
}
impl ZipTc for (TcTypeEq, TcTypeCmp) {
type Output = TcTypeCmp;
}
impl<B: BaseTypeWitnessTc> ZipTc for (TcTypeNe, B) {
type Output = TcTypeNe;
}
impl ZipTc for (TcTypeCmp, TcTypeEq) {
type Output = TcTypeCmp;
}
impl ZipTc for (TcTypeCmp, TcTypeNe) {
type Output = TcTypeNe;
}
impl ZipTc for (TcTypeCmp, TcTypeCmp) {
type Output = TcTypeCmp;
}
impl<A, B, C> ZipTc for (A, B, C)
where
A: BaseTypeWitnessTc,
B: BaseTypeWitnessTc,
C: BaseTypeWitnessTc,
(A, B): ZipTc,
(ZipTcOut<(A, B)>, C): ZipTc,
{
type Output = ZipTcOut<(ZipTcOut<(A, B)>, C)>;
}
impl<A, B, C, D> ZipTc<> for (A, B, C, D)
where
A: BaseTypeWitnessTc,
B: BaseTypeWitnessTc,
C: BaseTypeWitnessTc,
D: BaseTypeWitnessTc,
(A, B): ZipTc,
(C, D): ZipTc,
(ZipTcOut<(A, B)>, ZipTcOut<(C, D)>): ZipTc,
{
type Output = ZipTcOut<(ZipTcOut<(A, B)>, ZipTcOut<(C, D)>)>;
}
//////////////////////////////////////////////////////////////////////
macro_rules! declare_zip_items {
(
[$first_typa:ident ($($middle_typa:ident)*) $end_typa:ident]
$(#[$fn_attr:meta])*
fn $fn_name:ident($fn_param0:ident $(, $fn_param_rem:ident)*);
$($rem:tt)*
) => {
__declare_zip_items!{
[$first_typa ($($middle_typa)*) $end_typa]
[$first_typa $($middle_typa)* $end_typa]
$(#[$fn_attr])*
fn $fn_name ($fn_param0 $(, $fn_param_rem)*) ($fn_param0, $(, $fn_param_rem)*);
$($rem)*
}
}
}
macro_rules! __declare_zip_items {
(
[$first_typa:ident ($($middle_typa:ident)*) $end_typa:ident]
[$($ty_params:ident)*]
$(#[$fn_attr:meta])*
fn $fn_name:ident($($fn_param:ident),*) ($fn_param0:ident, $(, $fn_param_rem:ident)*);
$(#[$type_alias_attr:meta])*
type $type_alias:ident;
$(#[$trait_attr:meta])*
trait $trait:ident;
enum $ty_wit:ident ($($arg_wit:ident),*);
zip_method = $zip_method:ident;
count = $count:tt
) => {
#[doc = concat!(
"The type returned by zipping ",
$count,
" [`BaseTypeWitness`]es.",
)]
$(#[$type_alias_attr])*
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_65")))]
pub type $type_alias<$($ty_params),*> =
<$first_typa as $trait<$($middle_typa,)* $end_typa>>::Output;
#[doc = concat!(
"Computes the type that the [`",
stringify!($fn_name),
"`] function returns, ",
)]
$(#[$trait_attr])*
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_65")))]
pub trait $trait<
$($middle_typa: BaseTypeWitness,)*
$end_typa: BaseTypeWitness,
>: BaseTypeWitness
where
Self::L: Sized,
Self::R: Sized,
$(
$middle_typa::L: Sized,
$middle_typa::R: Sized,
)*
{
#[doc = concat!(
"The the type returned by zipping ",
$count, " [`BaseTypeWitness`] types"
)]
type Output: BaseTypeWitness<
L = (Self::L, $($middle_typa::L,)* $end_typa::L),
R = (Self::R, $($middle_typa::R,)* $end_typa::R),
>;
}
impl<$($ty_params,)*> $trait<$($middle_typa,)* $end_typa> for $first_typa
where
$($ty_params: BaseTypeWitness,)*
($($ty_params::TypeCtor,)*): ZipTc,
Self::L: Sized,
Self::R: Sized,
$(
$middle_typa::L: Sized,
$middle_typa::R: Sized,
)*
{
type Output =
TcToBaseTypeWitness<
ZipTcOut<($($ty_params::TypeCtor,)*)>,
($($ty_params::L,)*),
($($ty_params::R,)*),
>;
}
enum $ty_wit<$($ty_params,)* Ret: BaseTypeWitness>
where
$( $ty_params: BaseTypeWitness, )*
$first_typa::L: Sized,
$first_typa::R: Sized,
$(
$middle_typa::L: Sized,
$middle_typa::R: Sized,
)*
{
Eq {
$($arg_wit: TypeEq<$ty_params, TypeEq<$ty_params::L, $ty_params::R>>,)*
ret: TypeEq<
Ret,
TypeEq<($($ty_params::L,)*), ($($ty_params::R,)*)>
>
},
Ne {
#[allow(dead_code)]
contains_ne: SomeTypeArgIsNe<$($ty_params,)*>,
ret: TypeEq<Ret, TypeNe<($($ty_params::L,)*), ($($ty_params::R,)*)>>
},
Cmp {
ret: TypeEq<Ret, TypeCmp<($($ty_params::L,)*), ($($ty_params::R,)*)>>
},
}
impl<$($ty_params,)*> $ty_wit<$($ty_params,)* $type_alias<$($ty_params,)*>>
where
$first_typa: $trait<$($middle_typa,)* $end_typa>,
$first_typa::L: Sized,
$first_typa::R: Sized,
$(
$middle_typa: BaseTypeWitness,
$middle_typa::L: Sized,
$middle_typa::R: Sized,
)*
$end_typa: BaseTypeWitness,
{
const NEW: Self =
match ($($ty_params::WITNESS,)* $type_alias::<$($ty_params,)*>::WITNESS) {
($(MBTW::Eq($arg_wit),)* MBTW::Eq(ret)) => {
Self::Eq { $($arg_wit,)* ret }
}
(.., MBTW::Ne(ret)) => {
let contains_ne = SomeTypeArgIsNe::<$($ty_params,)*>::new();
Self::Ne { contains_ne, ret }
}
(.., MBTW::Cmp(ret)) => {
Self::Cmp {ret}
}
_ => panic!("BUG: invalid permutation of $trait"),
};
}
$(#[$fn_attr])*
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_65")))]
pub const fn $fn_name<$($ty_params,)*>(
$($fn_param: $ty_params,)*
) -> $type_alias<$($ty_params,)*>
where
$first_typa: BaseTypeWitness,
$first_typa::L: Sized,
$first_typa::R: Sized,
$(
$middle_typa: BaseTypeWitness,
$middle_typa::L: Sized,
$middle_typa::R: Sized,
)*
$end_typa: BaseTypeWitness,
$first_typa: $trait<$($middle_typa,)* $end_typa>
{
match $ty_wit::<$($ty_params,)* $type_alias<$($ty_params,)*>>::NEW {
$ty_wit::Eq {$($arg_wit,)* ret} =>
ret.to_left(TypeEq::$zip_method($($arg_wit.to_right($fn_param),)*)),
$ty_wit::Ne {contains_ne, ret} =>
ret.to_left(contains_ne.$fn_name($($fn_param,)*)),
$ty_wit::Cmp {ret} =>
ret.to_left(
MetaBaseTypeWit::to_cmp(A::WITNESS, $fn_param0)
.$zip_method($($fn_param_rem,)*)
),
}
}
};
}
declare_zip_items!{
[A () B]
/// Zips together two [`BaseTypeWitness`] types.
///
#[doc = return_type_docs!()]
///
/// # Example
///
/// ### Basic
///
/// This example shows all permutations of argument and return types.
///
/// ```rust
/// use typewit::{TypeCmp, TypeEq, TypeNe, type_ne};
/// use typewit::methods::zip2;
///
/// with::<u8, u8, bool, u16, u32>(
/// TypeEq::NEW,
/// type_ne!(u8, bool),
/// TypeCmp::Ne(type_ne!(u16, u32)),
/// );
///
/// const fn with<A, B, C, D, E>(eq: TypeEq<A, B>, ne: TypeNe<B, C>, cmp: TypeCmp<D, E>) {
/// let _: TypeEq<(A, B), (B, A)> = zip2(eq, eq.flip());
/// let _: TypeNe<(A, B), (B, C)> = zip2(eq, ne);
/// let _: TypeCmp<(A, D), (B, E)> = zip2(eq, cmp);
///
/// let _: TypeNe<(B, A), (C, B)> = zip2(ne, eq);
/// let _: TypeNe<(B, C), (C, B)> = zip2(ne, ne.flip());
/// let _: TypeNe<(B, D), (C, E)> = zip2(ne, cmp);
///
/// let _: TypeCmp<(D, A), (E, B)> = zip2(cmp, eq);
/// let _: TypeNe<(D, B), (E, C)> = zip2(cmp, ne);
/// let _: TypeCmp<(D, E), (E, D)> = zip2(cmp, cmp.flip());
///
/// }
/// ```
fn zip2(wit0, wit1);
type Zip2Out;
trait Zip2;
enum Zip2Wit (arg0, arg1);
zip_method = zip;
count = "two"
}
//////////////////////////////////////////////////////////////////////
declare_zip_items!{
[A (B) C]
/// Zips together three [`BaseTypeWitness`] types.
///
#[doc = return_type_docs!()]
///
/// # Example
///
/// ### Basic
///
/// This example shows basic usage.
///
/// ```rust
/// use typewit::{TypeCmp, TypeEq, TypeNe, type_eq, type_ne};
/// use typewit::methods::zip3;
///
/// with::<u8, u8, bool, u16, u32>(
/// TypeEq::NEW,
/// type_ne!(u8, bool),
/// TypeCmp::Ne(type_ne!(u16, u32)),
/// );
///
/// const fn with<A, B, C, D, E>(eq: TypeEq<A, B>, ne: TypeNe<B, C>, cmp: TypeCmp<D, E>) {
/// let _: TypeEq<(A, B, i64), (B, A, i64)> = zip3(eq, eq.flip(), type_eq::<i64>());
///
/// let _: TypeNe<(A, B, B), (B, A, C)> = zip3(eq, eq.flip(), ne);
///
/// let _: TypeCmp<(A, D, B), (B, E, A)> = zip3(eq, cmp, eq.flip());
/// }
/// ```
fn zip3(wit0, wit1, wit2);
type Zip3Out;
trait Zip3;
enum Zip3Wit (arg0, arg1, arg2);
zip_method = zip3;
count = "three"
}
//////////////////////////////////////////////////////////////////////
declare_zip_items!{
[A (B C) D]
/// Zips together four [`BaseTypeWitness`] types.
///
#[doc = return_type_docs!()]
///
/// # Example
///
/// ### Basic
///
/// This example shows basic usage.
///
/// ```rust
/// use typewit::{TypeCmp, TypeEq, TypeNe, type_eq, type_ne};
/// use typewit::methods::zip4;
///
/// with::<u8, u8, bool, u16, u32>(
/// TypeEq::NEW,
/// type_ne!(u8, bool),
/// TypeCmp::Ne(type_ne!(u16, u32)),
/// );
///
/// const fn with<A, B, C, D, E>(eq: TypeEq<A, B>, ne: TypeNe<B, C>, cmp: TypeCmp<D, E>) {
/// let _: TypeEq<(A, u64, B, i64), (B, u64, A, i64)> =
/// zip4(eq, type_eq(), eq.flip(), type_eq());
///
/// let _: TypeNe<(A, E, B, B), (B, D, A, C)> = zip4(eq, cmp.flip(), eq.flip(), ne);
///
/// let _: TypeCmp<(D, A, B, A), (E, B, A, B)> = zip4(cmp, eq, eq.flip(), eq);
/// }
/// ```
fn zip4(wit0, wit1, wit2, wit3);
type Zip4Out;
trait Zip4;
enum Zip4Wit (arg0, arg1, arg2, arg3);
zip_method = zip4;
count = "four"
}
//////////////////////////////////////////////////////////////////////
pub use with_const_marker::*;
mod with_const_marker {
use super::*;
use crate::type_fn::PairToArrayFn;
use core::marker::PhantomData;
// maps the type arguments of a BaseTypeWitness with `F`
struct MapWithFn<F>(PhantomData<F>);
impl<F, W> crate::TypeFn<W> for MapWithFn<F>
where
W: BaseTypeWitness,
F: crate::TypeFn<W::L> + crate::TypeFn<W::R>,
{
type Output = MapBaseTypeWitness<W, F>;
}
/// Combines a
/// `impl BaseTypeWitness<L = LT, R = RT>`
/// <br>with an `impl BaseTypeWitness<L = Usize<LN>, R = Usize<RN>>`
/// <br>returning an `impl BaseTypeWitness<L = [LT; LN], R = [RT; RN]>`.
///
#[doc = return_type_docs!()]
///
/// # Example
///
/// ### Return types
///
/// ```rust
/// use typewit::{
/// methods::in_array,
/// const_marker::Usize,
/// TypeCmp, TypeEq, TypeNe,
/// type_ne,
/// };
///
/// let eq_ty: TypeEq<i16, i16> = TypeEq::NEW;
/// let ne_ty: TypeNe<i16, u16> = type_ne!(i16, u16);
/// let cmp_ty: TypeCmp<i16, u16> = TypeCmp::Ne(type_ne!(i16, u16));
///
/// let eq_len: TypeEq<Usize<0>, Usize<0>> = TypeEq::NEW;
/// let ne_len: TypeNe<Usize<1>, Usize<2>> = Usize.equals(Usize).unwrap_ne();
/// let cmp_len: TypeCmp<Usize<3>, Usize<3>> = Usize.equals(Usize);
///
///
/// // if both arguments are TypeEq, this returns a TypeEq
/// let _: TypeEq<[i16; 0], [i16; 0]> = in_array(eq_ty, eq_len);
///
/// // if either of the arguments is a TypeNe, this returns a TypeNe
/// let _: TypeNe<[i16; 0], [u16; 0]> = in_array(ne_ty, eq_len);
/// let _: TypeNe<[i16; 1], [i16; 2]> = in_array(eq_ty, ne_len);
/// let _: TypeNe<[i16; 1], [u16; 2]> = in_array(ne_ty, ne_len);
/// let _: TypeNe<[i16; 1], [u16; 2]> = in_array(cmp_ty, ne_len);
///
/// // If there are TypeCmp args, and no TypeNe args, this returns a TypeCmp
/// assert!(matches!(in_array(eq_ty, cmp_len), TypeCmp::<[i16; 3], [i16; 3]>::Eq(_)));
/// assert!(matches!(in_array(cmp_ty, eq_len), TypeCmp::<[i16; 0], [u16; 0]>::Ne(_)));
/// assert!(matches!(in_array(cmp_ty, cmp_len), TypeCmp::<[i16; 3], [u16; 3]>::Ne(_)));
/// ```
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_65")))]
pub const fn in_array<A, B, LT, RT, const LN: usize, const RN: usize>(
wit0: A,
wit1: B,
) -> BaseTypeWitnessReparam<Zip2Out<A, B>, [LT; LN], [RT; RN]>
where
A: BaseTypeWitness<L = LT, R = RT>,
B: BaseTypeWitness<L = Usize<LN>, R = Usize<RN>>,
A: Zip2<B>
{
match Zip2Wit::<A, B, Zip2Out<A, B>>::NEW {
Zip2Wit::Eq {arg0, arg1, ret} =>
ret.project::<MapWithFn<PairToArrayFn>>()
.to_left(TypeEq::in_array(arg0.to_right(wit0), arg1.to_right(wit1))),
Zip2Wit::Ne {contains_ne, ret} =>
ret.project::<MapWithFn<PairToArrayFn>>()
.to_left(contains_ne.zip2(wit0, wit1).project::<PairToArrayFn>()),
Zip2Wit::Cmp {ret} =>
ret.project::<MapWithFn<PairToArrayFn>>().to_left(
MetaBaseTypeWit::to_cmp(A::WITNESS, wit0)
.in_array(wit1)
),
}
}
}

View File

@@ -0,0 +1,100 @@
#[cfg(feature = "rust_1_65")]
use crate::base_type_wit::MetaBaseTypeWit as MBTW;
use crate::{
base_type_wit::BaseTypeWitness as BTW,
TypeEq, TypeNe
};
// A `TypeEq` that's used as padding for the trailing type arguments of SomeTypeArgIsNe.
type PadTyEq = TypeEq<(), ()>;
// The first TypeNe in the 4 `BaseTypeWitness` type parameters
pub(crate) enum SomeTypeArgIsNe<A: BTW, B: BTW, C: BTW = PadTyEq, D: BTW = PadTyEq> {
A(TypeEq<A, TypeNe<A::L, A::R>>),
B(TypeEq<B, TypeNe<B::L, B::R>>),
C(TypeEq<C, TypeNe<C::L, C::R>>),
D(TypeEq<D, TypeNe<D::L, D::R>>),
}
#[cfg(feature = "rust_1_65")]
impl<A: BTW, B: BTW, C: BTW, D: BTW> SomeTypeArgIsNe<A, B, C, D> {
pub(crate) const TRY_NEW: Option<Self> = {
match (A::WITNESS, B::WITNESS, C::WITNESS, D::WITNESS) {
(MBTW::Ne(ne), _, _, _) => Some(Self::A(ne)),
(_, MBTW::Ne(ne), _, _) => Some(Self::B(ne)),
(_, _, MBTW::Ne(ne), _) => Some(Self::C(ne)),
(_, _, _, MBTW::Ne(ne)) => Some(Self::D(ne)),
_ => None,
}
};
pub(crate) const fn new() -> Self {
match Self::TRY_NEW {
Some(x) => x,
None => panic!("expected at least one type argument to be TypeNe"),
}
}
}
impl<A: BTW, B: BTW> SomeTypeArgIsNe<A, B, PadTyEq, PadTyEq>
where
A::L: Sized,
A::R: Sized,
{
#[inline(always)]
pub(crate) const fn zip2(self, _: A, _: B) -> TypeNe<(A::L, B::L), (A::R, B::R)> {
// SAFETY: either `A` or `B` is a TypeNe (PadTyEq isn't a TypeNe),
// therefore: `(A::L, B::L) != (A::R, B::R)`.
// (the function parameters are needed for soundness,
// since `TypeNe` guarantees type inequality at the value level)
unsafe { TypeNe::new_unchecked() }
}
}
impl<A: BTW, B: BTW, C: BTW> SomeTypeArgIsNe<A, B, C, PadTyEq>
where
A::L: Sized,
A::R: Sized,
B::L: Sized,
B::R: Sized,
{
#[inline(always)]
pub(crate) const fn zip3(
self,
_: A,
_: B,
_: C,
) -> TypeNe<(A::L, B::L, C::L), (A::R, B::R, C::R)> {
// SAFETY: either `A`, `B`, or `C is a TypeNe (PadTyEq isn't a TypeNe),
// therefore: `(A::L, B::L, C::L) != (A::R, B::R, C::R)`.
// (the function parameters are needed for soundness,
// since `TypeNe` guarantees type inequality at the value level)
unsafe { TypeNe::new_unchecked() }
}
}
impl<A: BTW, B: BTW, C: BTW, D: BTW> SomeTypeArgIsNe<A, B, C, D>
where
A::L: Sized,
A::R: Sized,
B::L: Sized,
B::R: Sized,
C::L: Sized,
C::R: Sized,
{
#[inline(always)]
pub(crate) const fn zip4(
self,
_: A,
_: B,
_: C,
_: D,
) -> TypeNe<(A::L, B::L, C::L, D::L), (A::R, B::R, C::R, D::R)> {
// SAFETY: either `A`, `B`, `C`, or `D` is a TypeNe,
// therefore: `(A::L, B::L, C::L, D::L) != (A::R, B::R, C::R, D::R)`.
// (the function parameters are needed for soundness,
// since `TypeNe` guarantees type inequality at the value level)
unsafe { TypeNe::new_unchecked() }
}
}

16
vendor/typewit/src/test_doc_lints.rs vendored Normal file
View File

@@ -0,0 +1,16 @@
#![deny(missing_docs)]
crate::simple_type_witness!{
/// Docs for enum
derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Equals)
pub enum AllDerives {
/// docs for U8 variant
U8 = u8,
/// docs for U16 variant
U16 = u16,
}
}

609
vendor/typewit/src/type_cmp.rs vendored Normal file
View File

@@ -0,0 +1,609 @@
use crate::{TypeEq, TypeNe};
#[cfg(feature = "rust_1_61")]
use crate::{BaseTypeWitness, MetaBaseTypeWit, SomeTypeArgIsNe};
use core::{
any::Any,
cmp::{Ordering, Eq, Ord, PartialEq, PartialOrd},
hash::{Hash, Hasher},
fmt::{self, Debug},
};
/// A witness of whether its `L` and `R` type parameters are the same or different types.
///
/// # Example
///
/// ### Custom array creation
///
/// (this example requires Rust 1.63.0, because of [`core::array::from_fn`]).
///
#[cfg_attr(not(feature = "rust_1_65"), doc = "```ignore")]
#[cfg_attr(feature = "rust_1_65", doc = "```rust")]
/// use typewit::{const_marker::Usize, TypeCmp, TypeEq, TypeNe};
///
/// let empty: [String; 0] = [];
/// assert_eq!(ArrayMaker::<String, 0>::empty().make(), empty);
///
/// assert_eq!(ArrayMaker::<u8, 2>::defaulted().make(), [0u8, 0u8]);
///
/// assert_eq!(ArrayMaker::with(|i| i.pow(2)).make(), [0usize, 1, 4, 9]);
///
///
/// enum ArrayMaker<T, const LEN: usize> {
/// NonEmpty(fn(usize) -> T, TypeNe<[T; LEN], [T; 0]>),
/// Empty(TypeEq<[T; LEN], [T; 0]>),
/// }
///
/// impl<T, const LEN: usize> ArrayMaker<T, LEN> {
/// pub fn make(self) -> [T; LEN] {
/// match self {
/// ArrayMaker::NonEmpty(func, _) => std::array::from_fn(func),
/// ArrayMaker::Empty(te) => te.to_left([]),
/// }
/// }
///
/// pub const fn defaulted() -> Self
/// where
/// T: Default
/// {
/// Self::with(|_| Default::default())
/// }
///
/// pub const fn with(func: fn(usize) -> T) -> Self {
/// match Usize::<LEN>.equals(Usize::<0>) // : TypeCmp<Usize<LEN>, Usize<0>>
/// .project::<ArrayFn<T>>() // : TypeCmp<[T; LEN], [T; 0]>
/// {
/// TypeCmp::Ne(ne) => ArrayMaker::NonEmpty(func, ne),
/// TypeCmp::Eq(eq) => ArrayMaker::Empty(eq),
/// }
/// }
/// }
///
/// impl<T> ArrayMaker<T, 0> {
/// pub const fn empty() -> Self {
/// Self::Empty(TypeEq::NEW)
/// }
/// }
///
/// impl<T, const LEN: usize> Copy for ArrayMaker<T, LEN> {}
///
/// impl<T, const LEN: usize> Clone for ArrayMaker<T, LEN> {
/// fn clone(&self) -> Self { *self }
/// }
///
/// typewit::inj_type_fn! {
/// // Declares `struct ArrayFn`, which implements `InjTypeFn<Usize<LEN>>`:
/// // an injective type-level function from `Usize<LEN>` to `[T; LEN]`
/// struct ArrayFn<T>;
/// impl<const LEN: usize> Usize<LEN> => [T; LEN]
/// }
/// ```
pub enum TypeCmp<L: ?Sized, R: ?Sized>{
/// proof of `L == R`
Eq(TypeEq<L, R>),
/// proof of `L != R`
Ne(TypeNe<L, R>),
}
impl<L: ?Sized, R: ?Sized> TypeCmp<L, R> {
/// Constructs a `TypeCmp<L, R>` by comparing the `L` and `R` types for equality.
///
/// # Example
///
/// ```rust
/// use typewit::TypeCmp;
///
/// let eq: TypeCmp<u8, u8> = TypeCmp::with_any();
/// assert!(matches!(eq, TypeCmp::Eq(_)));
///
/// let ne = TypeCmp::<u8, i8>::with_any();
/// assert!(matches!(ne, TypeCmp::Ne(_)));
/// ```
#[deprecated = concat!(
"fallout of `https://github.com/rust-lang/rust/issues/97156`,",
"`TypeId::of::<L>() != TypeId::of::<R>()` does not imply `L != R`"
)]
pub fn with_any() -> Self
where
L: Sized + Any,
R: Sized + Any,
{
#[allow(deprecated)]
if let Some(equal) = TypeEq::with_any() {
TypeCmp::Eq(equal)
} else if let Some(unequal) = TypeNe::with_any() {
TypeCmp::Ne(unequal)
} else {
unreachable!()
}
}
/// Swaps the type arguments of this `TypeCmp`
///
/// # Example
///
/// ```rust
/// use typewit::{TypeCmp, type_ne};
///
/// const TC: TypeCmp<u8, i8> = TypeCmp::Ne(type_ne!(u8, i8));
///
/// const TK: TypeCmp<i8, u8> = TC.flip();
///
/// ```
pub const fn flip(self) -> TypeCmp<R, L> {
match self {
TypeCmp::Eq(te) => TypeCmp::Eq(te.flip()),
TypeCmp::Ne(te) => TypeCmp::Ne(te.flip()),
}
}
/// Joins this `TypeCmp<L, R>` with a `TypeEq<Q, L>`, producing a `TypeCmp<Q, R>`.
///
/// # Example
///
/// ```rust
/// use typewit::{TypeCmp, TypeEq, type_ne};
///
/// const TC: TypeCmp<str, [u8]> = type_ne!(str, [u8]).to_cmp();
///
/// const fn foo<A: ?Sized>(eq: TypeEq<A, str>) {
/// let _tc: TypeCmp<A, [u8]> = TC.join_left(eq);
/// }
/// ```
pub const fn join_left<Q: ?Sized>(self, left: TypeEq<Q, L>) -> TypeCmp<Q, R> {
match self {
TypeCmp::Eq(te) => TypeCmp::Eq(left.join(te)),
TypeCmp::Ne(te) => TypeCmp::Ne(te.join_left(left)),
}
}
/// Joins this `TypeCmp<L, R>` with a `TypeEq<R, Q>`, producing a `TypeCmp<L, Q>`.
///
/// # Example
///
/// ```rust
/// use typewit::{TypeCmp, TypeEq, type_ne};
///
/// const NE: TypeCmp<String, Vec<u8>> = type_ne!(String, Vec<u8>).to_cmp();
///
/// const fn foo<A>(eq: TypeEq<Vec<u8>, A>) {
/// let _ne: TypeCmp<String, A> = NE.join_right(eq);
/// }
/// ```
pub const fn join_right<Q: ?Sized>(self, right: TypeEq<R, Q>) -> TypeCmp<L, Q> {
match self {
TypeCmp::Eq(te) => TypeCmp::Eq(te.join(right)),
TypeCmp::Ne(te) => TypeCmp::Ne(te.join_right(right)),
}
}
/// Converts this `TypeCmp<L, R>` into an `Option<TypeEq<L, R>>`.
///
/// # Example
///
/// ```rust
/// use typewit::{TypeCmp, TypeEq, type_ne};
///
/// let eq: TypeCmp<u8, u8> = TypeCmp::Eq(TypeEq::NEW);
/// assert!(matches!(eq.eq(), Some(TypeEq::<u8, u8>{..})));
///
/// let ne = TypeCmp::Ne(type_ne!(u8, i8));
/// assert!(matches!(ne.eq(), None::<TypeEq<u8, i8>>));
/// ```
pub const fn eq(self) -> Option<TypeEq<L, R>> {
match self {
TypeCmp::Eq(te) => Some(te),
TypeCmp::Ne(_) => None,
}
}
/// Converts this `TypeCmp<L, R>` into an `Option<TypeNe<L, R>>`.
///
/// # Example
///
/// ```rust
/// use typewit::{TypeCmp, TypeEq, TypeNe, type_ne};
///
/// let eq: TypeCmp<u8, u8> = TypeCmp::Eq(TypeEq::NEW);
/// assert!(matches!(eq.ne(), None::<TypeNe<u8, u8>>));
///
/// let ne = TypeCmp::Ne(type_ne!(u8, i8));
/// assert!(matches!(ne.ne(), Some(TypeNe::<u8, i8>{..})));
/// ```
pub const fn ne(self) -> Option<TypeNe<L, R>> {
match self {
TypeCmp::Eq(_) => None,
TypeCmp::Ne(te) => Some(te),
}
}
/// Returns whether this `TypeCmp` is a `TypeCmp::Eq`.
///
/// # Example
///
/// ```rust
/// use typewit::{TypeCmp, TypeEq, TypeNe, type_ne};
///
/// const EQ: TypeCmp<u8, u8> = TypeEq::NEW.to_cmp();
/// assert_eq!(EQ.is_eq(), true);
///
/// const NE: TypeCmp<i8, u8> = type_ne!(i8, u8).to_cmp();
/// assert_eq!(NE.is_eq(), false);
/// ```
pub const fn is_eq(self) -> bool {
matches!(self, TypeCmp::Eq(_))
}
/// Returns whether this `TypeCmp` is a `TypeCmp::Ne`.
///
/// # Example
///
/// ```rust
/// use typewit::{TypeCmp, TypeEq, TypeNe, type_ne};
///
/// const EQ: TypeCmp<u8, u8> = TypeEq::NEW.to_cmp();
/// assert_eq!(EQ.is_ne(), false);
///
/// const NE: TypeCmp<i8, u8> = type_ne!(i8, u8).to_cmp();
/// assert_eq!(NE.is_ne(), true);
/// ```
pub const fn is_ne(self) -> bool {
matches!(self, TypeCmp::Ne(_))
}
/// Returns the contained `TypeEq`
///
/// # Panic
///
/// Panics if the contained value is a `TypeNe`.
///
/// # Example
///
/// ```rust
/// use typewit::{TypeCmp, TypeEq};
///
/// let eq: TypeCmp<u8, u8> = TypeCmp::Eq(TypeEq::NEW);
/// assert!(matches!(eq.unwrap_eq(), TypeEq::<u8, u8>{..}));
/// ```
#[track_caller]
pub const fn unwrap_eq(self) -> TypeEq<L, R> {
match self {
TypeCmp::Eq(te) => te,
TypeCmp::Ne(_) => panic!("called `TypeCmp::unwrap_eq` on a `TypeNe` value"),
}
}
/// Returns the contained `TypeEq`
///
/// # Panic
///
/// Panics if the contained value is a `TypeNe`, with `msg` as the panic message.
///
/// # Example
///
/// ```rust
/// use typewit::{TypeCmp, TypeEq};
///
/// let eq: TypeCmp<u8, u8> = TypeCmp::Eq(TypeEq::NEW);
/// assert!(matches!(eq.expect_eq("they're the same type!"), TypeEq::<u8, u8>{..}));
/// ```
#[track_caller]
pub const fn expect_eq(self, msg: &str) -> TypeEq<L, R> {
match self {
TypeCmp::Eq(te) => te,
TypeCmp::Ne(_) => panic!("{}", msg),
}
}
/// Returns the contained `TypeNe`
///
/// # Panic
///
/// Panics if the contained value is a `TypeEq`.
///
/// # Example
///
/// ```rust
/// use typewit::{TypeCmp, TypeNe, type_ne};
///
/// let ne = TypeCmp::Ne(type_ne!(u8, i8));
/// assert!(matches!(ne.unwrap_ne(), TypeNe::<u8, i8>{..}));
/// ```
#[track_caller]
pub const fn unwrap_ne(self) -> TypeNe<L, R> {
match self {
TypeCmp::Eq(_) => panic!("called `TypeCmp::unwrap_ne` on a `TypeEq` value"),
TypeCmp::Ne(te) => te,
}
}
/// Returns the contained `TypeNe`
///
/// # Panic
///
/// Panics if the contained value is a `TypeEq`, with `msg` as the panic message.
///
/// # Example
///
/// ```rust
/// use typewit::{TypeCmp, TypeNe, type_ne};
///
/// let ne = TypeCmp::Ne(type_ne!(u8, i8));
/// assert!(matches!(ne.expect_ne("but u8 isn't i8..."), TypeNe::<u8, i8>{..}));
/// ```
#[track_caller]
pub const fn expect_ne(self, msg: &str) -> TypeNe<L, R> {
match self {
TypeCmp::Eq(_) => panic!("{}", msg),
TypeCmp::Ne(te) => te,
}
}
}
#[cfg(feature = "rust_1_61")]
macro_rules! alternative_docs {
($func:expr) => {concat!(
"# Alternative\n",
"\n",
"[`methods::", $func,"`](crate::methods::", $func, ") \n",
"is an alternative to this function. \n",
"\n",
"This method always returns `TypeCmp`, \n",
"while [that function](crate::methods::", $func, ")\n",
"returns [`TypeNe`] when any argument is a `TypeNe`.\n",
"\n",
"# Returned variant\n",
"\n",
"This returns either [`TypeCmp::Eq`] or [`TypeCmp::Ne`]",
" depending on the arguments:\n",
"- if all arguments (including `self`)",
" are [`TypeEq`] or [`TypeCmp::Eq`], this returns [`TypeCmp::Eq`] \n",
"- if any argument (including `self`) ",
"is a [`TypeNe`] or [`TypeCmp::Ne`], this returns [`TypeCmp::Ne`] \n",
)};
}
#[cfg(feature = "rust_1_61")]
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_61")))]
impl<L, R> TypeCmp<L, R> {
/// Combines this `TypeCmp<L, R>` with a [`BaseTypeWitness`] type to produce a
/// `TypeCmp<(L, A::L), (R, A::R)>`.
///
#[doc = alternative_docs!("zip2")]
///
/// # Example
///
/// ```rust
/// use typewit::{TypeCmp, TypeEq, TypeNe, type_ne};
///
///
/// const NE: TypeNe<u8, i8> = type_ne!(u8, i8);
/// const EQ: TypeEq<u16, u16> = TypeEq::NEW;
/// const TC_NE: TypeCmp<u32, u64> = TypeCmp::Ne(type_ne!(u32, u64));
/// const TC_EQ: TypeCmp<i64, i64> = TypeCmp::Eq(TypeEq::NEW);
///
/// assert!(matches!(
/// TC_EQ.zip(NE),
/// TypeCmp::<(i64, u8), (i64, i8)>::Ne(_),
/// ));
///
/// assert!(matches!(
/// TC_EQ.zip(EQ),
/// TypeCmp::<(i64, u16), (i64, u16)>::Eq(_),
/// ));
///
/// assert!(matches!(
/// TC_EQ.zip(TC_EQ),
/// TypeCmp::<(i64, i64), (i64, i64)>::Eq(_),
/// ));
///
/// assert!(matches!(
/// TC_EQ.zip(TC_NE),
/// TypeCmp::<(i64, u32), (i64, u64)>::Ne(_),
/// ));
/// ```
pub const fn zip<A>(self, other: A) -> TypeCmp<(L, A::L), (R, A::R)>
where
A: BaseTypeWitness,
{
let other = MetaBaseTypeWit::to_cmp(A::WITNESS, other);
match (self, other) {
(TypeCmp::Eq(tel), TypeCmp::Eq(ter)) => {
TypeCmp::Eq(tel.zip(ter))
}
(TypeCmp::Ne(ne), _) => {
TypeCmp::Ne(SomeTypeArgIsNe::A(TypeEq::NEW).zip2(ne, other))
}
(_, TypeCmp::Ne(ne)) => {
TypeCmp::Ne(SomeTypeArgIsNe::B(TypeEq::NEW).zip2(self, ne))
}
}
}
/// Combines this `TypeCmp<L, R>` with two [`BaseTypeWitness`] types to produce a
/// `TypeCmp<(L, A::L, B::L), (R, A::R, B::R)>`.
///
#[doc = alternative_docs!("zip3")]
///
/// # Example
///
/// ```rust
/// use typewit::{TypeCmp, TypeEq, TypeNe, type_ne};
///
///
/// const NE: TypeNe<u8, i8> = type_ne!(u8, i8);
/// const EQ: TypeEq<u16, u16> = TypeEq::NEW;
/// const TC_NE: TypeCmp<u32, u64> = TypeCmp::Ne(type_ne!(u32, u64));
/// const TC_EQ: TypeCmp<i64, i64> = TypeCmp::Eq(TypeEq::NEW);
///
/// assert!(matches!(
/// TC_EQ.zip3(EQ, NE),
/// TypeCmp::<(i64, u16, u8), (i64, u16, i8)>::Ne(_),
/// ));
///
/// assert!(matches!(
/// TC_EQ.zip3(EQ, TC_EQ),
/// TypeCmp::<(i64, u16, i64), (i64, u16, i64)>::Eq(_),
/// ));
///
/// assert!(matches!(
/// TC_EQ.zip3(NE, TC_NE),
/// TypeCmp::<(i64, u8, u32), (i64, i8, u64)>::Ne(_),
/// ));
/// ```
pub const fn zip3<A, B>(self, arg0: A, arg1: B) -> TypeCmp<(L, A::L, B::L), (R, A::R, B::R)>
where
A: BaseTypeWitness,
A::L: Sized,
A::R: Sized,
B: BaseTypeWitness,
{
let arg0 = MetaBaseTypeWit::to_cmp(A::WITNESS, arg0);
let arg1 = MetaBaseTypeWit::to_cmp(B::WITNESS, arg1);
match (self, arg0, arg1) {
(TypeCmp::Eq(te0), TypeCmp::Eq(te1), TypeCmp::Eq(te2)) => {
TypeCmp::Eq(te0.zip3(te1, te2))
}
(TypeCmp::Ne(ne), _, _) => {
TypeCmp::Ne(SomeTypeArgIsNe::A(TypeEq::NEW).zip3(ne, arg0, arg1))
}
(_, TypeCmp::Ne(ne), _) => {
TypeCmp::Ne(SomeTypeArgIsNe::B(TypeEq::NEW).zip3(self, ne, arg1))
}
(_, _, TypeCmp::Ne(ne)) => {
TypeCmp::Ne(SomeTypeArgIsNe::C(TypeEq::NEW).zip3(self, arg0, ne))
}
}
}
/// Combines this `TypeCmp<L, R>` with three [`BaseTypeWitness`] types to produce a
/// `TypeCmp<(L, A::L, B::L, C::L), (R, A::R, B::R, C::R)>`.
///
#[doc = alternative_docs!("zip4")]
///
///
/// # Example
///
/// ```rust
/// use typewit::{TypeCmp, TypeEq, TypeNe, type_ne};
///
///
/// const NE: TypeNe<u8, i8> = type_ne!(u8, i8);
/// const EQ: TypeEq<u16, u16> = TypeEq::NEW;
/// const TC_NE: TypeCmp<u32, u64> = TypeCmp::Ne(type_ne!(u32, u64));
/// const TC_EQ: TypeCmp<i64, i64> = TypeCmp::Eq(TypeEq::NEW);
///
/// assert!(matches!(
/// TC_EQ.zip4(EQ, NE, TC_NE),
/// TypeCmp::<(i64, u16, u8, u32), (i64, u16, i8, u64)>::Ne(_),
/// ));
///
/// assert!(matches!(
/// TC_EQ.zip4(EQ, TC_EQ, EQ),
/// TypeCmp::<(i64, u16, i64, u16), (i64, u16, i64, u16)>::Eq(_),
/// ));
/// ```
pub const fn zip4<A, B, C>(
self,
arg0: A,
arg1: B,
arg2: C,
) -> TypeCmp<(L, A::L, B::L, C::L), (R, A::R, B::R, C::R)>
where
A: BaseTypeWitness,
A::L: Sized,
A::R: Sized,
B: BaseTypeWitness,
B::L: Sized,
B::R: Sized,
C: BaseTypeWitness,
{
let arg0 = MetaBaseTypeWit::to_cmp(A::WITNESS, arg0);
let arg1 = MetaBaseTypeWit::to_cmp(B::WITNESS, arg1);
let arg2 = MetaBaseTypeWit::to_cmp(C::WITNESS, arg2);
match (self, arg0, arg1, arg2) {
(TypeCmp::Eq(te0), TypeCmp::Eq(te1), TypeCmp::Eq(te2), TypeCmp::Eq(te3)) => {
TypeCmp::Eq(te0.zip4(te1, te2, te3))
}
(TypeCmp::Ne(ne), _, _, _) => {
TypeCmp::Ne(SomeTypeArgIsNe::A(TypeEq::NEW).zip4(ne, arg0, arg1, arg2))
}
(_, TypeCmp::Ne(ne), _, _) => {
TypeCmp::Ne(SomeTypeArgIsNe::B(TypeEq::NEW).zip4(self, ne, arg1, arg2))
}
(_, _, TypeCmp::Ne(ne), _) => {
TypeCmp::Ne(SomeTypeArgIsNe::C(TypeEq::NEW).zip4(self, arg0, ne, arg2))
}
(_, _, _, TypeCmp::Ne(ne)) => {
TypeCmp::Ne(SomeTypeArgIsNe::D(TypeEq::NEW).zip4(self, arg0, arg1, ne))
}
}
}
}
// using this instead of `mod extra_type_cmp_methods;`
// to document the impls in the submodule below the constructors.
include!{"./type_cmp/extra_type_cmp_methods.rs"}
impl<L: ?Sized, R: ?Sized> Copy for TypeCmp<L, R> {}
impl<L: ?Sized, R: ?Sized> Clone for TypeCmp<L, R> {
fn clone(&self) -> Self {
*self
}
}
impl<L: ?Sized, R: ?Sized> Debug for TypeCmp<L, R> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
TypeCmp::Eq(x) => Debug::fmt(x, f),
TypeCmp::Ne(x) => Debug::fmt(x, f),
}
}
}
impl<L: ?Sized, R: ?Sized> PartialEq for TypeCmp<L, R> {
fn eq(&self, other: &Self) -> bool {
self.is_eq() == other.is_eq()
}
}
impl<L: ?Sized, R: ?Sized> PartialOrd for TypeCmp<L, R> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.is_eq().partial_cmp(&other.is_eq())
}
}
impl<L: ?Sized, R: ?Sized> Ord for TypeCmp<L, R> {
fn cmp(&self, other: &Self) -> Ordering {
self.is_eq().cmp(&other.is_eq())
}
}
impl<L: ?Sized, R: ?Sized> Eq for TypeCmp<L, R> {}
impl<L: ?Sized, R: ?Sized> Hash for TypeCmp<L, R> {
fn hash<H>(&self, state: &mut H)
where H: Hasher
{
match self {
TypeCmp::Eq(x) => Hash::hash(x, state),
TypeCmp::Ne(x) => Hash::hash(x, state),
}
}
}

View File

@@ -0,0 +1,326 @@
use crate::type_fn::{InjTypeFn, InvokeAlias, CallInjFn, UncallFn};
#[cfg(feature = "alloc")]
use alloc::boxed::Box;
///
/// # Why `InjTypeFn`
///
/// Both [`map`](Self::map) and [`project`](Self::project)
/// require that the function is [injective]
/// so that `TypeCmp`'s arguments don't change from
/// being equal to unequal or viceversa.
///
/// [injective]: mod@crate::type_fn#injective
///
impl<L: ?Sized, R: ?Sized> TypeCmp<L, R> {
/// Maps the type arguments of this `TypeCmp`
/// by using the `F` [injective type-level function](crate::InjTypeFn).
///
/// Use this function over [`project`](Self::project)
/// if you want the type of the passed in function to be inferred.
///
/// # Example
///
/// ```rust
/// use typewit::{TypeCmp, TypeEq, TypeNe, inj_type_fn, type_ne};
///
/// use std::num::Wrapping;
///
///
/// const EQ: TypeCmp<u8, u8> = TypeEq::NEW.to_cmp();
/// assert!(matches!(EQ.map(WrappingFn), TypeCmp::<Wrapping<u8>, Wrapping<u8>>::Eq(_)));
///
/// const NE: TypeCmp<i8, u8> = type_ne!(i8, u8).to_cmp();
/// assert!(matches!(NE.map(WrappingFn), TypeCmp::<Wrapping<i8>, Wrapping<u8>>::Ne(_)));
///
///
/// inj_type_fn!{
/// struct WrappingFn;
///
/// impl<T> T => Wrapping<T>
/// }
/// ```
pub const fn map<F>(
self: TypeCmp<L, R>,
func: F,
) -> TypeCmp<CallInjFn<InvokeAlias<F>, L>, CallInjFn<InvokeAlias<F>, R>>
where
InvokeAlias<F>: InjTypeFn<L> + InjTypeFn<R>
{
match self {
TypeCmp::Eq(te) => TypeCmp::Eq(te.map::<F>(func)),
TypeCmp::Ne(te) => TypeCmp::Ne(te.map::<F>(func)),
}
}
/// Maps the type arguments of this `TypeCmp`
/// by using the `F` [injective type-level function](crate::InjTypeFn).
///
/// Use this function over [`map`](Self::map)
/// if you want to specify the type of the passed in function explicitly.
///
/// # Example
///
/// ```rust
/// use typewit::{TypeCmp, TypeEq, TypeNe, inj_type_fn, type_ne};
///
/// use std::mem::ManuallyDrop as ManDrop;
///
///
/// const EQ: TypeCmp<u8, u8> = TypeEq::NEW.to_cmp();
/// assert!(matches!(EQ.project::<ManDropFn>(), TypeCmp::<ManDrop<u8>, ManDrop<u8>>::Eq(_)));
///
/// const NE: TypeCmp<i8, u8> = type_ne!(i8, u8).to_cmp();
/// assert!(matches!(NE.project::<ManDropFn>(), TypeCmp::<ManDrop<i8>, ManDrop<u8>>::Ne(_)));
///
///
/// inj_type_fn!{
/// struct ManDropFn;
///
/// impl<T> T => ManDrop<T>
/// }
/// ```
pub const fn project<F>(
self: TypeCmp<L, R>,
) -> TypeCmp<CallInjFn<InvokeAlias<F>, L>, CallInjFn<InvokeAlias<F>, R>>
where
InvokeAlias<F>: InjTypeFn<L> + InjTypeFn<R>
{
match self {
TypeCmp::Eq(te) => TypeCmp::Eq(te.project::<F>()),
TypeCmp::Ne(te) => TypeCmp::Ne(te.project::<F>()),
}
}
/// Maps the type arguments of this `TypeCmp`
/// by using the [reversed](crate::RevTypeFn)
/// version of the `F` type-level function.
///
/// Use this function over [`unproject`](Self::unproject)
/// if you want the type of the passed in function to be inferred.
///
/// # Example
///
/// ```rust
/// use typewit::{TypeCmp, TypeEq, TypeNe, inj_type_fn, type_ne};
///
/// use std::num::Wrapping;
///
///
/// const EQ: TypeCmp<Wrapping<u8>, Wrapping<u8>> = TypeEq::NEW.to_cmp();
///
/// assert!(matches!(EQ.unmap(WrappingFn), TypeCmp::<u8, u8>::Eq(_)));
///
/// const NE: TypeCmp<Wrapping<i8>, Wrapping<u8>> =
/// type_ne!(Wrapping<i8>, Wrapping<u8>).to_cmp();
///
/// assert!(matches!(NE.unmap(WrappingFn), TypeCmp::<i8, u8>::Ne(_)));
///
///
/// inj_type_fn!{
/// struct WrappingFn;
///
/// impl<T> T => Wrapping<T>
/// }
/// ```
pub const fn unmap<F>(
self,
func: F,
) -> TypeCmp<UncallFn<InvokeAlias<F>, L>, UncallFn<InvokeAlias<F>, R>>
where
InvokeAlias<F>: crate::RevTypeFn<L> + crate::RevTypeFn<R>
{
match self {
TypeCmp::Eq(te) => TypeCmp::Eq(te.unmap::<F>(func)),
TypeCmp::Ne(te) => TypeCmp::Ne(te.unmap::<F>(func)),
}
}
/// Maps the type arguments of this `TypeCmp`
/// by using the [reversed](crate::RevTypeFn)
/// version of the `F` type-level function.
///
/// Use this function over [`unmap`](Self::unmap)
/// if you want to specify the type of the passed in function explicitly.
///
///
/// # Example
///
/// ```rust
/// use typewit::{TypeCmp, TypeEq, TypeNe, inj_type_fn, type_ne};
///
/// use std::mem::MaybeUninit as MaybeUn;
///
///
/// const EQ: TypeCmp<MaybeUn<u8>, MaybeUn<u8>> = TypeEq::NEW.to_cmp();
///
/// assert!(matches!(EQ.unproject::<MaybeUnFn>(), TypeCmp::<u8, u8>::Eq(_)));
///
/// const NE: TypeCmp<MaybeUn<i8>, MaybeUn<u8>> =
/// type_ne!(MaybeUn<i8>, MaybeUn<u8>).to_cmp();
///
/// assert!(matches!(NE.unproject::<MaybeUnFn>(), TypeCmp::<i8, u8>::Ne(_)));
///
///
/// inj_type_fn!{
/// struct MaybeUnFn;
///
/// impl<T> T => MaybeUn<T>
/// }
/// ```
pub const fn unproject<F>(
self,
) -> TypeCmp<UncallFn<InvokeAlias<F>, L>, UncallFn<InvokeAlias<F>, R>>
where
InvokeAlias<F>: crate::RevTypeFn<L> + crate::RevTypeFn<R>
{
match self {
TypeCmp::Eq(te) => TypeCmp::Eq(te.unproject::<F>()),
TypeCmp::Ne(te) => TypeCmp::Ne(te.unproject::<F>()),
}
}
/// Converts a `TypeCmp<L, R>` to `TypeCmp<&L, &R>`
///
/// # Example
///
/// ```rust
/// use typewit::{TypeCmp, TypeEq, TypeNe, type_ne};
///
/// const EQ: TypeCmp<u8, u8> = TypeEq::NEW.to_cmp();
/// assert!(matches!(EQ.in_ref(), TypeCmp::<&u8, &u8>::Eq(_)));
///
/// const NE: TypeCmp<i8, u8> = type_ne!(i8, u8).to_cmp();
/// assert!(matches!(NE.in_ref(), TypeCmp::<&i8, &u8>::Ne(_)));
///
/// ```
pub const fn in_ref<'a>(self) -> TypeCmp<&'a L, &'a R> {
match self {
TypeCmp::Eq(te) => TypeCmp::Eq(te.in_ref()),
TypeCmp::Ne(te) => TypeCmp::Ne(te.in_ref()),
}
}
crate::utils::conditionally_const!{
feature = "rust_1_83";
/// Converts a `TypeCmp<L, R>` to `TypeCmp<&mut L, &mut R>`
///
/// # Constness
///
/// This requires the `"rust_1_83"` crate feature to be a `const fn`.
///
/// # Example
///
/// ```rust
/// use typewit::{TypeCmp, TypeEq, TypeNe, type_ne};
///
/// const EQ: TypeCmp<u8, u8> = TypeEq::NEW.to_cmp();
/// assert!(matches!(EQ.in_mut(), TypeCmp::<&mut u8, &mut u8>::Eq(_)));
///
/// const NE: TypeCmp<i8, u8> = type_ne!(i8, u8).to_cmp();
/// assert!(matches!(NE.in_mut(), TypeCmp::<&mut i8, &mut u8>::Ne(_)));
///
/// ```
pub fn in_mut['a](self) -> TypeCmp<&'a mut L, &'a mut R> {
match self {
TypeCmp::Eq(te) => TypeCmp::Eq(te.in_mut()),
TypeCmp::Ne(te) => TypeCmp::Ne(te.in_mut()),
}
}
}
/// Converts a `TypeCmp<L, R>` to `TypeCmp<Box<L>, Box<R>>`
///
/// # Example
///
/// ```rust
/// use typewit::{TypeCmp, TypeEq, TypeNe, type_ne};
///
/// const EQ: TypeCmp<u8, u8> = TypeEq::NEW.to_cmp();
/// assert!(matches!(EQ.in_box(), TypeCmp::<Box<u8>, Box<u8>>::Eq(_)));
///
/// const NE: TypeCmp<i8, u8> = type_ne!(i8, u8).to_cmp();
/// assert!(matches!(NE.in_box(), TypeCmp::<Box<i8>, Box<u8>>::Ne(_)));
///
/// ```
#[cfg(feature = "alloc")]
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
pub const fn in_box(self) -> TypeCmp<Box<L>, Box<R>> {
match self {
TypeCmp::Eq(te) => TypeCmp::Eq(te.in_box()),
TypeCmp::Ne(te) => TypeCmp::Ne(te.in_box()),
}
}
}
#[cfg(feature = "rust_1_61")]
use crate::const_marker::Usize;
#[cfg(feature = "rust_1_61")]
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_61")))]
impl<L, R> TypeCmp<L, R> {
/// Combines `TypeCmp<L, R>` and a
/// `O:`[`BaseTypeWitness`]`<L = Usize<UL>, R = Usize<UR>>`
/// into `TypeCmp<[L; UL], [R; UR]>`
///
/// [`BaseTypeWitness`]: crate::BaseTypeWitness
///
#[doc = alternative_docs!("in_array")]
///
/// # Example
///
/// ### Basic
///
/// ```rust
/// use typewit::{
/// const_marker::Usize,
/// TypeCmp, TypeEq, TypeNe,
/// type_ne,
/// };
///
/// let cmp_eq_ty: TypeCmp<i32, i32> = TypeCmp::Eq(TypeEq::NEW);
/// let cmp_ne_ty: TypeCmp<i64, u64> = TypeCmp::Ne(type_ne!(i64, u64));
///
/// let eq_len: TypeEq<Usize<0>, Usize<0>> = TypeEq::NEW;
/// let ne_len: TypeNe<Usize<1>, Usize<2>> = Usize.equals(Usize).unwrap_ne();
/// let cmp_eq_len: TypeCmp<Usize<3>, Usize<3>> = Usize.equals(Usize);
/// let cmp_ne_len: TypeCmp<Usize<5>, Usize<8>> = Usize.equals(Usize);
///
/// assert!(matches!(cmp_eq_ty.in_array(eq_len), TypeCmp::<[i32; 0], [i32; 0]>::Eq(_)));
/// assert!(matches!(cmp_eq_ty.in_array(ne_len), TypeCmp::<[i32; 1], [i32; 2]>::Ne(_)));
/// assert!(matches!(cmp_eq_ty.in_array(cmp_eq_len), TypeCmp::<[i32; 3], [i32; 3]>::Eq(_)));
/// assert!(matches!(cmp_eq_ty.in_array(cmp_ne_len), TypeCmp::<[i32; 5], [i32; 8]>::Ne(_)));
///
/// assert!(matches!(cmp_ne_ty.in_array(eq_len), TypeCmp::<[i64; 0], [u64; 0]>::Ne(_)));
/// assert!(matches!(cmp_ne_ty.in_array(ne_len), TypeCmp::<[i64; 1], [u64; 2]>::Ne(_)));
/// assert!(matches!(cmp_ne_ty.in_array(cmp_eq_len), TypeCmp::<[i64; 3], [u64; 3]>::Ne(_)));
/// assert!(matches!(cmp_ne_ty.in_array(cmp_ne_len), TypeCmp::<[i64; 5], [u64; 8]>::Ne(_)));
/// ```
pub const fn in_array<O, const UL: usize, const UR: usize>(
self,
other: O,
) -> TypeCmp<[L; UL], [R; UR]>
where
O: BaseTypeWitness<L = Usize<UL>, R = Usize<UR>>
{
use crate::type_fn::PairToArrayFn as PTAF;
let other = MetaBaseTypeWit::to_cmp(O::WITNESS, other);
match (self, other) {
(TypeCmp::Eq(tel), TypeCmp::Eq(ter)) => {
TypeCmp::Eq(tel.in_array(ter))
}
(TypeCmp::Ne(ne), _) => {
TypeCmp::Ne(SomeTypeArgIsNe::A(TypeEq::NEW).zip2(ne, other).project::<PTAF>())
}
(_, TypeCmp::Ne(ne)) => {
TypeCmp::Ne(SomeTypeArgIsNe::B(TypeEq::NEW).zip2(self, ne).project::<PTAF>())
}
}
}
}

82
vendor/typewit/src/type_constructors.rs vendored Normal file
View File

@@ -0,0 +1,82 @@
//! Higher Kinded Types for [`BaseTypeWitness`]es
#![cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_65")))]
use crate::{BaseTypeWitness, TypeCmp, TypeEq, TypeNe};
use core::fmt::Debug;
/// The type constructor for a [`BaseTypeWitness`],
/// only implemented for [`TcTypeCmp`]/[`TcTypeEq`]/[`TcTypeNe`].
///
/// A type constructor is a "type" which needs to be provided
/// generic arguments to produce a concrete type.
///
/// This crate emulates type constructors for [`BaseTypeWitness`] types by using this trait,
/// concrete types are produced with the [`Type`](Self::Type) associated constant.
///
pub trait BaseTypeWitnessTc: 'static + Copy + Debug {
/// The [`BaseTypeWitness`] type that corresponds to this type constructor.
///
/// For [`TcTypeCmp`], this is [`TypeCmp`]`<L, R>`
/// <br>
/// For [`TcTypeEq`], this is [`TypeEq`]`<L, R>`
/// <br>
/// For [`TcTypeNe`], this is [`TypeNe`]`<L, R>`
///
type Type<L: ?Sized, R: ?Sized>: BaseTypeWitness<L = L, R = R, TypeCtor = Self>;
}
/// Computes a [`BaseTypeWitness`] type from a [`BaseTypeWitnessTc`]
pub type TcToBaseTypeWitness<TC, L, R> = <TC as BaseTypeWitnessTc>::Type::<L, R>;
/// Queries the [`BaseTypeWitnessTc`] of a [`BaseTypeWitness`]
pub type BaseTypeWitnessToTc<W> = <W as BaseTypeWitness>::TypeCtor;
/// Computes `W:`[`BaseTypeWitness`] with its type arguments replaced with `L` and `R`
pub type BaseTypeWitnessReparam<W, L, R> =
<BaseTypeWitnessToTc<W> as BaseTypeWitnessTc>::Type::<
L,
R,
>;
/// The type returned by `W::project::<F>()`,
/// where `W` is a [`BaseTypeWitness`]
pub type MapBaseTypeWitness<W, F> =
<BaseTypeWitnessToTc<W> as BaseTypeWitnessTc>::Type::<
crate::CallFn<F, <W as BaseTypeWitness>::L>,
crate::CallFn<F, <W as BaseTypeWitness>::R>,
>;
/////////////////////////////////////////////////////////////////////////////
/// The [*type constructor*](BaseTypeWitnessTc) for [`TypeCmp`].
#[derive(Debug, Copy, Clone)]
pub struct TcTypeCmp;
impl BaseTypeWitnessTc for TcTypeCmp {
type Type<L: ?Sized, R: ?Sized> = TypeCmp<L, R>;
}
/// The [*type constructor*](BaseTypeWitnessTc) for [`TypeEq`].
#[derive(Debug, Copy, Clone)]
pub struct TcTypeEq;
impl BaseTypeWitnessTc for TcTypeEq {
type Type<L: ?Sized, R: ?Sized> = TypeEq<L, R>;
}
/// The [*type constructor*](BaseTypeWitnessTc) for [`TypeNe`].
#[derive(Debug, Copy, Clone)]
pub struct TcTypeNe;
impl BaseTypeWitnessTc for TcTypeNe {
type Type<L: ?Sized, R: ?Sized> = TypeNe<L, R>;
}

1232
vendor/typewit/src/type_eq.rs vendored Normal file

File diff suppressed because it is too large Load Diff

89
vendor/typewit/src/type_eq_ne_guts.rs vendored Normal file
View File

@@ -0,0 +1,89 @@
// $type_cmp is either TypeEq or TypeNe
macro_rules! declare_zip_helper {($_:tt $type_cmp_ty:ident) => {
macro_rules! zip_impl {
// Using more specific patterns for $L and $R to prevent usage of macros,
// which can expand to different values on each use
($_( $type_cmp:ident [$_($L:ident)::*, $_($R:ident)::*] ),* $_(,)*) => {
$_(
let _te: $type_cmp_ty<$_($L)::*, $_($R)::*> = $type_cmp;
)*
// SAFETY:
// `$type_cmp_ty<$_($L)::*, $_($R)::*>` for every passed `$type_cmp`
// implies `$type_cmp_ty<(L0, L1, ...), (R0, R1, ...)>`
unsafe {
$type_cmp_ty::<($_($_($L)::*,)*), ($_($_($R)::*,)*)>::new_unchecked()
}
}
}
}} pub(crate) use declare_zip_helper;
// $type_cmp is either TypeEq or TypeNe
macro_rules! declare_helpers {($_:tt $type_cmp_ty:ident $tyfn:ident $callfn:ident) => {
macro_rules! projected_type_cmp {
($type_cmp:expr, $L:ty, $R:ty, $F:ty) => ({
// Safety(TypeEq):
// this takes a `TypeEq<$L, $R>`,
// which implies `TypeEq<CallFn<$tyfn, $L>, CallFn<$tyfn, $R>>`.
//
// Safety(TypeNe):
// this takes a `TypeNe<$L, $R>`,
// and requires `$tyfn: InjTypeFn<$L> + InjTypeFn<$R>`,
// (`InjTypeFn` guarantees that unequal arguments map to unequal return values),
// which implies `TypeNe<CallInjFn<$tyfn, $L>, CallInjFn<$tyfn, $R>>`.
unsafe {
__ProjectVars::<$F, $L, $R> {
te: $type_cmp,
projected_te: $type_cmp_ty::new_unchecked(),
}.projected_te
}
})
} use projected_type_cmp;
struct __ProjectVars<F, L: ?Sized, R: ?Sized>
where
InvokeAlias<F>: $tyfn<L> + $tyfn<R>
{
#[allow(dead_code)]
te: $type_cmp_ty<L, R>,
// $type_cmp_ty<L, R>
// implies $type_cmp_ty<$callfn<F, L>, $callfn<F, R>>
projected_te: $type_cmp_ty<$callfn<InvokeAlias<F>, L>, $callfn<InvokeAlias<F>, R>>,
}
macro_rules! unprojected_type_cmp {
($type_cmp:expr, $L:ty, $R:ty, $F:ty) => ({
// safety:
// This macro takes a `$type_cmp_ty<$L, $R>` value,
// which implies `$type_cmp_ty<UncallFn<F, $L>, UncallFn<F, $R>>`
//
// The properties section of RevTypeFn guarantees this for
// both TypeEq and TypeNe
unsafe {
__UnprojectVars::<$F, $L, $R> {
te: $type_cmp,
unprojected_te: $type_cmp_ty::new_unchecked(),
}.unprojected_te
}
})
}
struct __UnprojectVars<F, L: ?Sized, R: ?Sized>
where
InvokeAlias<F>: crate::RevTypeFn<L> + crate::RevTypeFn<R>
{
#[allow(dead_code)]
te: $type_cmp_ty<L, R>,
// $type_cmp_ty<L, R>
// implies $type_cmp_ty<UncallFn<F, L>, UncallFn<F, R>>
//
// The properties section of RevTypeFn guarantees this for
// both TypeEq and TypeNe
unprojected_te: $type_cmp_ty<UncallFn<InvokeAlias<F>, L>, UncallFn<InvokeAlias<F>, R>>,
}
}} pub(crate) use declare_helpers;

332
vendor/typewit/src/type_fn.rs vendored Normal file
View File

@@ -0,0 +1,332 @@
//! Type-level functions.
//!
//! Type-level functions come in two flavors:
//! [injective](#injective), and [non-injective](#non-injective)
//!
//!
//! # Injective
//!
//! An injective function is any function `f` for which `a != b` implies `f(a) != f(b)`.
//! <br>(For both injective and non-injective functions, `f(a) != f(b)` implies `a != b`)
//!
//! The [`InjTypeFn`] trait encodes injective type-level functions,
//! requiring the type to implement both [`TypeFn`] and [`RevTypeFn`].
//!
//!
//! ### Example: injective function
//!
//! ```rust
//! # use typewit::CallInjFn;
//! #
//! typewit::inj_type_fn!{
//! struct Upcast;
//!
//! impl u8 => u16;
//! impl u16 => u32;
//! impl u32 => u64;
//! impl u64 => u128;
//! }
//! let _: CallInjFn<Upcast, u8> = 3u16;
//! let _: CallInjFn<Upcast, u16> = 5u32;
//! ```
//!
//! Because `Upcast` is injective,
//! it is possible to query the argument from the returned value:
//!
//! ```rust
//! # use typewit::UncallFn;
//! #
//! let _: UncallFn<Upcast, u16> = 3u8;
//! let _: UncallFn<Upcast, u128> = 5u64;
//! #
//! # typewit::inj_type_fn!{
//! # struct Upcast;
//! #
//! # impl u8 => u16;
//! # impl u16 => u32;
//! # impl u32 => u64;
//! # impl u64 => u128;
//! # }
//! ```
//!
//! # Non-injective
//!
//! The [`TypeFn`] trait allows implementors to be non-injective.
//!
//! ### Example: non-injective function
//!
//! ```rust
//! typewit::type_fn!{
//! struct Bar;
//!
//! impl<T> Vec<T> => T;
//! impl<T> Box<T> => T;
//! }
//! ```
//! `Bar` is *non*-injective because it maps both `Vec<T>` and `Box<T>` to `T`.
//!
//!
//! [`TypeFn`]: crate::type_fn::TypeFn
//! [`CallFn`]: crate::type_fn::CallFn
//!
use core::marker::PhantomData;
mod injective;
pub use self::injective::*;
pub(crate) use self::injective::simple_inj_type_fn;
#[doc(no_inline)]
pub use crate::inj_type_fn;
#[doc(no_inline)]
pub use crate::type_fn;
/// A function that operates purely on the level of types.
///
/// These can be used in `typewit` to
/// [map the type arguments of `TypeEq`](crate::TypeEq::project).
///
/// Type-level functions can also be declared with the
/// [`type_fn`](macro@crate::type_fn) macro.
///
/// # Properties
///
/// These are properties about `TypeFn` implementors that users can rely on.
///
/// For any given `F: TypeFn<A> + TypeFn<B>` these hold:
///
/// 1. If `A == B`, then `CallFn<F, A> == CallFn<F, B>`.
/// 2. If `CallFn<F, A> != CallFn<F, B>`, then `A != B`.
///
/// # Examples
///
/// ### Manual Implementation
///
/// ```rust
/// use typewit::{TypeFn, CallFn};
///
/// let string: CallFn<AddOutput<String>, &str> = "foo".to_string() + ", bar";
/// let _: String = string;
/// assert_eq!(string, "foo, bar");
///
///
/// struct AddOutput<Lhs>(core::marker::PhantomData<Lhs>);
///
/// // This part is optional,
/// // only necessary to pass the function as a value, not just as a type.
/// impl<Lhs> AddOutput<Lhs> {
/// const NEW: Self = Self(core::marker::PhantomData);
/// }
///
/// impl<Lhs, Rhs> TypeFn<Rhs> for AddOutput<Lhs>
/// where
/// Lhs: core::ops::Add<Rhs>
/// {
/// type Output = Lhs::Output;
/// }
/// ```
///
/// ### Macro-based Implementation
///
/// This example uses the [`type_fn`](macro@crate::type_fn) macro
/// to declare the type-level function,
/// and is otherwise equivalent to the manual one.
///
/// ```rust
/// use typewit::CallFn;
///
/// let string: CallFn<AddOutput<String>, &str> = "foo".to_string() + ", bar";
/// let _: String = string;
/// assert_eq!(string, "foo, bar");
///
/// typewit::type_fn! {
/// struct AddOutput<Lhs>;
///
/// impl<Rhs> Rhs => Lhs::Output
/// where Lhs: core::ops::Add<Rhs>
/// }
/// ```
///
#[cfg_attr(feature = "rust_1_83", diagnostic::on_unimplemented(
message = "{Self} is not a type-level function over `{T}`",
))]
pub trait TypeFn<T: ?Sized> {
/// The return value of the function
type Output: ?Sized;
/// Helper constant for adding asserts in the `TypeFn` impl;
const TYPE_FN_ASSERTS: () = ();
}
/// Calls the `F` [type-level function](TypeFn) with `T` as its argument.
///
/// For `F:`[`InjTypeFn<T>`](crate::InjTypeFn), it's better to
/// use [`CallInjFn`] instead of this type alias.
///
///
/// # Example
///
/// ```rust
/// use typewit::CallFn;
/// use core::ops::Mul;
///
/// assert_eq!(mul(3u8, &5u8), 15u8);
///
/// fn mul<L, R>(l: L, r: R) -> CallFn<MulOutput<L>, R>
/// where
/// L: core::ops::Mul<R>
/// {
/// l * r
/// }
///
/// // Declares `struct MulOutput<Lhs>`,
/// // a type-level function from `Rhs` to the return type of `Lhs * Rhs`.
/// typewit::type_fn! {
/// struct MulOutput<Lhs>;
///
/// impl<Rhs> Rhs => <Lhs as Mul<Rhs>>::Output
/// where Lhs: core::ops::Mul<Rhs>
/// }
/// ```
///
pub type CallFn<F, T> = <F as TypeFn<T>>::Output;
///////////////////////////////////////////////////////
/// Type-level function from `T` to `&'a T`
pub struct GRef<'a>(PhantomData<fn() -> &'a ()>);
impl<'a> GRef<'a> {
/// Make a value of this type-level function
pub const NEW: Self = Self(PhantomData);
}
simple_inj_type_fn!{
impl['a, T: 'a + ?Sized] (T => &'a T) for GRef<'a>
}
////////////////
/// Type-level function from `T` to `&'a mut T`
pub struct GRefMut<'a>(PhantomData<fn() -> &'a mut ()>);
impl<'a> GRefMut<'a> {
/// Make a value of this type-level function
pub const NEW: Self = Self(PhantomData);
}
simple_inj_type_fn!{
impl['a, T: 'a + ?Sized] (T => &'a mut T) for GRefMut<'a>
}
////////////////
/// Type-level function from `T` to `Box<T>`
#[cfg(feature = "alloc")]
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
pub struct GBox;
#[cfg(feature = "alloc")]
simple_inj_type_fn!{
impl[T: ?Sized] (T => alloc::boxed::Box<T>) for GBox
}
////////////////
/// Type-level identity function
pub struct FnIdentity;
simple_inj_type_fn!{
impl[T: ?Sized] (T => T) for FnIdentity
}
////////////////
/// Type-level function which implements `TypeFn` by delegating to `F`
///
/// This is mostly a workaround to write `F: TypeFn<T>` bounds in Rust 1.57.0
/// (trait bounds in `const fn`s were stabilized in Rust 1.61.0).
///
/// Because `Foo<F>: Trait`-style bounds unintentionally work in 1.57.0,
/// this crate uses `Invoke<F>: TypeFn<T>`
/// when the `"rust_1_61"` feature is disabled,
/// and `F: TypeFn<T>` when it is enabled.
///
pub struct Invoke<F>(PhantomData<fn() -> F>);
impl<F> Copy for Invoke<F> {}
impl<F> Clone for Invoke<F> {
fn clone(&self) -> Self {
*self
}
}
impl<F> Invoke<F> {
/// Constructs an `Invoke`
pub const NEW: Self = Self(PhantomData);
}
impl<F, T: ?Sized> TypeFn<T> for Invoke<F>
where
F: TypeFn<T>
{
type Output = CallFn<F, T>;
}
impl<F, R: ?Sized> RevTypeFn<R> for Invoke<F>
where
F: RevTypeFn<R>,
{
type Arg = UncallFn<F, R>;
}
////////////////////////////////////////////////////////////////////////////////
impl<F, T: ?Sized> TypeFn<T> for PhantomData<F>
where
F: TypeFn<T>
{
type Output = CallFn<F, T>;
}
impl<F, R: ?Sized> RevTypeFn<R> for PhantomData<F>
where
F: RevTypeFn<R>,
{
type Arg = UncallFn<F, R>;
}
////////////////////////////////////////////////////////////////////////////////
mod uses_const_marker {
use crate::const_marker::Usize;
/// TypeFn from `(T, Usize<N>)` to `[T; N]`
pub(crate) struct PairToArrayFn;
super::simple_inj_type_fn!{
impl[T, const N: usize] ((T, Usize<N>) => [T; N]) for PairToArrayFn
}
}
pub(crate) use uses_const_marker::*;
// This type alias makes it so that docs for newer Rust versions don't
// show `Invoke<F>`, keeping the method bounds the same as in 1.0.0.
#[cfg(not(feature = "rust_1_61"))]
pub(crate) type InvokeAlias<F> = Invoke<F>;
#[cfg(feature = "rust_1_61")]
pub(crate) type InvokeAlias<F> = F;

356
vendor/typewit/src/type_fn/injective.rs vendored Normal file
View File

@@ -0,0 +1,356 @@
//! Injective type-level functions
use crate::TypeFn;
use core::marker::PhantomData;
/// An [injective] type-level function
///
/// This trait is implemented automatically when both
/// [`TypeFn`] and [`RevTypeFn`] are implemented, and the function is [injective].
/// `InjTypeFn` cannot be manually implemented.
///
/// # Properties
///
/// These are properties about `InjTypeFn` that users can rely on.
///
/// For any given `F: InjTypeFn<A> + InjTypeFn<B>` these hold:
///
/// 1. If `A == B`, then `CallInjFn<F, A> == CallInjFn<F, B>`.
/// 2. If `CallInjFn<F, A> == CallInjFn<F, B>`, then `A == B`.
/// 3. If `A != B`, then `CallInjFn<F, A> != CallInjFn<F, B>`.
/// 4. If `CallInjFn<F, A> != CallInjFn<F, B>`, then `A != B`.
///
///
/// # Examples
///
/// ### Macro-based Implementation
///
/// ```rust
/// use typewit::{CallInjFn, UncallFn, inj_type_fn};
///
/// let _: CallInjFn<BoxFn, u32> = Box::new(3u32);
/// let _: UncallFn<BoxFn, Box<u32>> = 3u32;
///
/// inj_type_fn!{
/// struct BoxFn;
///
/// impl<T: ?Sized> T => Box<T>
/// }
/// ```
///
/// ### Non-macro Implementation
///
/// ```rust
/// use typewit::{CallInjFn, RevTypeFn, TypeFn, UncallFn};
///
/// let _: CallInjFn<BoxFn, u32> = Box::new(3u32);
/// let _: UncallFn<BoxFn, Box<u32>> = 3u32;
///
///
/// struct BoxFn;
///
/// impl<T: ?Sized> TypeFn<T> for BoxFn {
/// type Output = Box<T>;
///
/// // Asserts that this impl of `TypeFn` for `BoxFn` is injective.
/// const TYPE_FN_ASSERTS: () = { let _: CallInjFn<Self, T>; };
/// }
///
/// impl<T: ?Sized> RevTypeFn<Box<T>> for BoxFn {
/// type Arg = T;
/// }
///
/// ```
///
/// [injective]: mod@crate::type_fn#injective
#[cfg_attr(feature = "rust_1_83", diagnostic::on_unimplemented(
message = "{Self} is not an injective type-level function over `{A}`"
))]
pub trait InjTypeFn<A: ?Sized>: TypeFn<A, Output = Self::Ret> + RevTypeFn<Self::Ret, Arg = A> {
/// Return value of the function
type Ret: ?Sized;
}
impl<F, A: ?Sized, R: ?Sized> InjTypeFn<A> for F
where
F: TypeFn<A, Output = R>,
F: RevTypeFn<R, Arg = A>,
{
type Ret = R;
}
/// The inverse of [`TypeFn`],
/// for getting the argument of a [`TypeFn`](crate::type_fn::TypeFn)
/// from its return value.
///
/// # Properties
///
/// These are properties about `RevTypeFn` that users can rely on.
///
/// For any given `F: RevTypeFn<R> + RevTypeFn<O>` these hold:
///
/// 1. If `R == O`, then `UncallFn<F, R> == UncallFn<F, O>`
///
/// 2. If `R != O`, then `UncallFn<F, R> != UncallFn<F, O>`
///
/// Disclaimer: this trait **does not** by itself ensure that a function is
/// [injective],
/// since `RevTypeFn<Ret>` can't know if `Self::Arg` is the only argument
/// that could produce `Ret`.
///
/// # Examples
///
/// ### Macro-based impl
///
/// ```rust
/// use std::ops::Range;
///
/// use typewit::{RevTypeFn, UncallFn};
///
/// let array = [3usize, 5];
///
/// // Getting the argument of `ArrayFn` from its return value
/// let value: UncallFn<ArrayFn<2>, [usize; 2]> = array[0];
///
/// assert_eq!(value, 3usize);
///
/// typewit::inj_type_fn!{
/// struct ArrayFn<const N: usize>;
/// impl<T> T => [T; N]
/// }
/// ```
///
/// ### Manual impl
///
/// ```rust
/// use std::ops::Range;
///
/// use typewit::{CallInjFn, RevTypeFn, TypeFn, UncallFn};
///
/// let array = [3usize, 5];
///
/// // Getting the argument of `ArrayFn` from its return value
/// let value: UncallFn<ArrayFn<2>, [usize; 2]> = array[0];
///
/// assert_eq!(value, 3usize);
///
/// struct ArrayFn<const N: usize>;
///
/// impl<T, const N: usize> TypeFn<T> for ArrayFn<N> {
/// type Output = [T; N];
///
/// // Ensures that this impl of `TypeFn` for `ArrayFn` is injective.
/// const TYPE_FN_ASSERTS: () = { let _: CallInjFn<Self, T>; };
/// }
/// impl<T, const N: usize> RevTypeFn<[T; N]> for ArrayFn<N> {
/// type Arg = T;
/// }
/// ```
///
/// ### Non-injective function
///
/// As mentioned above, this trait doesn't make a function [injective].
///
/// In the example below, `NonInjective` isn't injective, because it maps different
/// arguments to the same return value:
///
/// ```rust
/// use typewit::{CallFn, RevTypeFn, TypeFn, UncallFn};
///
/// let _: CallFn<NonInjective, Vec<u8>> = 3u8;
/// let _: CallFn<NonInjective, String> = 5u8;
///
/// let _: UncallFn<NonInjective, u8> = ();
///
///
/// struct NonInjective;
///
/// impl<T> TypeFn<T> for NonInjective {
/// type Output = u8;
/// }
///
/// impl RevTypeFn<u8> for NonInjective {
/// type Arg = ();
/// }
/// ```
///
/// [injective]: mod@crate::type_fn#injective
#[cfg_attr(feature = "rust_1_83", diagnostic::on_unimplemented(
message = "{Self} does not have an reverse type-level function from `{Ret}`",
note = "consider declaring `{Self}` with the `typewit::inj_type_fn` macro",
))]
pub trait RevTypeFn<Ret: ?Sized>: TypeFn<Self::Arg, Output = Ret> {
/// The argument to this function with `Ret` as the return value.
type Arg: ?Sized;
}
/// Queries the argument to a `F: `[`TypeFn`] from its return value.
///
/// # Example
///
/// ```rust
/// use typewit::UncallFn;
///
/// let vect = vec![3u32, 5, 8];
/// let value: UncallFn<VecFn, Vec<u32>> = vect[1];
/// assert_eq!(value, 5u32);
///
/// typewit::inj_type_fn!{
/// struct VecFn;
/// impl<T> T => Vec<T>
/// }
/// ```
pub type UncallFn<F, Ret> = <F as RevTypeFn<Ret>>::Arg;
/// [`CallFn`](crate::CallFn) with an additional `F:`[`InjTypeFn<A>`] requirement,
/// which helps with type inference.
///
/// # Example
///
/// ```rust
/// use typewit::{InjTypeFn, CallInjFn};
///
/// // inferred return type
/// let inferred_ret = upcast(3u8);
/// assert_eq!(inferred_ret, 3);
///
/// // inferred argument type
/// let inferred_arg: u32 = upcast(5);
/// assert_eq!(inferred_arg, 5);
///
/// // Because the return type is `CallInjFn<_, I>`,
/// // this can infer `I` from the return type,
/// fn upcast<I>(int: I) -> CallInjFn<Upcast, I>
/// where
/// Upcast: InjTypeFn<I>,
/// CallInjFn<Upcast, I>: From<I>,
/// {
/// int.into()
/// }
///
///
/// typewit::inj_type_fn!{
/// struct Upcast;
///
/// impl u8 => u16;
/// impl u16 => u32;
/// impl u32 => u64;
/// impl u64 => u128;
/// }
/// ```
///
/// As of October 2023, replacing `CallInjFn` with `CallFn` can cause type inference errors:
///
/// ```text
/// error[E0277]: the trait bound `Upcast: TypeFn<{integer}>` is not satisfied
/// --> src/type_fn/injective.rs:132:32
/// |
/// 11 | let inferred_arg: u32 = upcast(5);
/// | ------ ^ the trait `TypeFn<{integer}>` is not implemented for `Upcast`
/// | |
/// | required by a bound introduced by this call
/// |
/// = help: the following other types implement trait `TypeFn<T>`:
/// <Upcast as TypeFn<u16>>
/// <Upcast as TypeFn<u32>>
/// <Upcast as TypeFn<u64>>
/// <Upcast as TypeFn<u8>>
/// ```
pub type CallInjFn<F, A> = <F as InjTypeFn<A>>::Ret;
macro_rules! simple_inj_type_fn {
(
impl[$($impl:tt)*] ($arg:ty => $ret:ty) for $func:ty
$(where[$($where:tt)*])?
) => {
impl<$($impl)*> crate::type_fn::TypeFn<$arg> for $func
$(where $($where)*)?
{
type Output = $ret;
}
impl<$($impl)*> crate::type_fn::RevTypeFn<$ret> for $func
$(where $($where)*)?
{
type Arg = $arg;
}
};
} pub(crate) use simple_inj_type_fn;
////////////////////////////////////////////////////////////////////////////////
/// Reverses an [`InjTypeFn`], its arguments become return values,
/// and its return values become arguments.
///
/// # Examples
///
/// ### Permutations
///
/// The different ways this function can be combined with [`CallFn`] and
/// [`UncallFn`]
///
/// ```rust
/// use typewit::type_fn::{CallFn, FnRev, UncallFn};
///
/// let _: CallFn<FnRev<Swap>, Right> = Left;
/// let _: UncallFn< Swap, Right> = Left;
///
/// let _: CallFn< Swap, Up> = Down;
/// let _: UncallFn<FnRev<Swap>, Up> = Down;
///
/// typewit::inj_type_fn!{
/// struct Swap;
///
/// impl Left => Right;
/// impl Up => Down;
/// }
///
/// struct Left;
/// struct Right;
/// struct Up;
/// struct Down;
/// ```
///
/// [`CallFn`]: crate::CallFn
pub struct FnRev<F: ?Sized>(PhantomData<fn() -> F>);
impl<F: ?Sized> FnRev<F> {
/// Constructs a `FnRev`.
pub const NEW: Self = Self(PhantomData);
}
impl<F> FnRev<F> {
/// Constructs a `FnRev` from `&F`
pub const fn from_ref(_f: &F) -> Self {
Self::NEW
}
}
impl<F, A: ?Sized> TypeFn<A> for FnRev<F>
where
F: RevTypeFn<A>
{
type Output = UncallFn<F, A>;
}
impl<F, R: ?Sized> RevTypeFn<R> for FnRev<F>
where
F: InjTypeFn<R>
{
type Arg = CallInjFn<F, R>;
}
#[test]
fn test_fnrev_equivalence(){
fn _foo<A, F: InjTypeFn<A>>() {
let _ = crate::TypeEq::<CallInjFn<FnRev<F>, F::Ret>, UncallFn<F, F::Ret>>::NEW;
let _ = crate::TypeEq::<UncallFn<FnRev<F>, A>, CallInjFn<F, A>>::NEW;
}
}

81
vendor/typewit/src/type_identity.rs vendored Normal file
View File

@@ -0,0 +1,81 @@
use crate::TypeEq;
/// Emulation of `T == U` bounds.
///
/// This trait emulates `T == U` bounds with `T: Identity<Type = U>`.
///
/// # Projection
///
/// Because this trait uses [`TypeEq`] for casting between `Self` and [`Self::Type`],
/// you can transform the arguments of that `TypeEq` to cast any composition of those types,
/// e.g: cast between `Vec<Self>` and `Vec<Self::Type>`
///
/// # Example
///
/// ### Type Parameter Alias
///
/// (this example requires Rust 1.61.0, because it uses trait bounds in a `const fn`)
///
#[cfg_attr(not(feature = "rust_1_61"), doc = "```ignore")]
#[cfg_attr(feature = "rust_1_61", doc = "```rust")]
/// use typewit::{Identity, TypeEq};
///
/// assert_eq!(foo(3), [3, 3]);
///
/// assert_eq!(foo::<&str, 2, _>("hello"), ["hello", "hello"]);
///
///
/// const fn foo<T, const N: usize, R>(val: T) -> R
/// where
/// // emulates a `[T; N] == R` bound
/// [T; N]: Identity<Type = R>,
/// T: Copy,
/// {
/// Identity::TYPE_EQ // returns a `TypeEq<[T; N], R>`
/// .to_right([val; N]) // casts `[T; N]` to `R`
/// }
/// ```
///
/// ### Projection
///
/// Demonstrating that any projection of `Self` and `Self::Type` can
/// be casted to each other.
///
/// ```rust
/// use typewit::{Identity, TypeEq, type_fn};
///
/// assert_eq!(make_vec::<u8>(), vec![3, 5, 8]);
///
/// fn make_vec<T>() -> Vec<T>
/// where
/// T: Identity<Type = u8>
/// {
/// let te: TypeEq<Vec<T>, Vec<u8>> = T::TYPE_EQ.project::<VecFn>();
///
/// te.to_left(vec![3, 5, 8]) // casts `Vec<u8>` to `Vec<T>`
/// }
///
/// type_fn!{
/// // A type-level function (TypeFn implementor) from `T` to `Vec<T>`
/// struct VecFn;
/// impl<T> T => Vec<T>
/// }
/// ```
///
pub trait Identity {
/// The same type as `Self`,
/// used to emulate type equality bounds (`T == U`)
/// with associated type equality constraints
/// (`T: Identity<Type = U>`).
type Type: ?Sized;
/// Proof that `Self` is the same type as `Self::Type`,
/// provides methods for casting between `Self` and `Self::Type`.
const TYPE_EQ: TypeEq<Self, Self::Type>;
}
impl<T: ?Sized> Identity for T {
type Type = T;
const TYPE_EQ: TypeEq<Self, Self::Type> = TypeEq::NEW;
}

View File

@@ -0,0 +1,370 @@
#[cfg(feature = "alloc")]
use alloc::boxed::Box;
use crate::type_fn::{InjTypeFn, InvokeAlias, CallInjFn, UncallFn};
#[cfg(feature = "rust_1_61")]
use crate::const_marker::Usize;
crate::type_eq_ne_guts::declare_helpers!{
$
TypeNe
InjTypeFn
CallInjFn
}
///
/// # Why `InjTypeFn`
///
/// Both [`map`](Self::map) and [`project`](Self::project)
/// require that the function is [injective]
/// so that `TypeNe`'s arguments stay unequal.
///
/// [injective]: mod@crate::type_fn#injective
///
impl<L: ?Sized, R: ?Sized> TypeNe<L, R> {
/// Maps the type arguments of this `TypeNe`
/// by using the `F` [injective type-level function](crate::InjTypeFn).
///
/// Use this function over [`project`](Self::project)
/// if you want the type of the passed in function to be inferred.
///
/// # Example
///
/// ```rust
/// use typewit::{TypeNe, inj_type_fn, type_ne};
///
/// const NE: TypeNe<u8, u16> = type_ne!(u8, u16);
///
/// const N3: TypeNe<[u8; 0], [u16; 0]> = NE.map(ArrayFn::NEW);
///
/// inj_type_fn!{
/// struct ArrayFn<const LEN: usize>;
///
/// impl<T> T => [T; LEN]
/// }
/// ```
pub const fn map<F>(
self: TypeNe<L, R>,
_func: F,
) -> TypeNe<CallInjFn<InvokeAlias<F>, L>, CallInjFn<InvokeAlias<F>, R>>
where
InvokeAlias<F>: InjTypeFn<L> + InjTypeFn<R>
{
core::mem::forget(_func);
projected_type_cmp!{self, L, R, InvokeAlias<F>}
}
/// Maps the type arguments of this `TypeNe`
/// by using the `F` [injective type-level function](crate::InjTypeFn).
///
/// Use this function over [`map`](Self::map)
/// if you want to specify the type of the passed in function explicitly.
///
/// # Example
///
/// ```rust
/// use typewit::{TypeNe, inj_type_fn, type_ne};
///
/// const NE: TypeNe<u8, u16> = type_ne!(u8, u16);
///
/// const N3: TypeNe<Vec<u8>, Vec<u16>> = NE.project::<VecFn>();
///
/// inj_type_fn!{
/// struct VecFn;
///
/// impl<T> T => Vec<T>
/// }
/// ```
pub const fn project<F>(
self: TypeNe<L, R>,
) -> TypeNe<CallInjFn<InvokeAlias<F>, L>, CallInjFn<InvokeAlias<F>, R>>
where
InvokeAlias<F>: InjTypeFn<L> + InjTypeFn<R>
{
projected_type_cmp!{self, L, R, InvokeAlias<F>}
}
/// Maps the type arguments of this `TypeNe`
/// by using the [reversed](crate::RevTypeFn)
/// version of the `F` type-level function.
///
/// Use this function over [`unproject`](Self::unproject)
/// if you want the type of the passed in function to be inferred.
///
/// # Example
///
/// ```rust
/// use typewit::{TypeNe, inj_type_fn, type_ne};
///
/// use std::cmp::Ordering as CmpOrdering;
/// use std::sync::atomic::Ordering as MemOrdering;
///
/// const NE: TypeNe<[CmpOrdering], [MemOrdering]> = type_ne!([CmpOrdering], [MemOrdering]);
///
///
/// const N3: TypeNe<CmpOrdering, MemOrdering> = NE.unmap(SliceFn);
///
/// inj_type_fn!{
/// struct SliceFn;
///
/// impl<T> T => [T]
/// }
/// ```
pub const fn unmap<F>(
self,
func: F,
) -> TypeNe<UncallFn<InvokeAlias<F>, L>, UncallFn<InvokeAlias<F>, R>>
where
InvokeAlias<F>: crate::RevTypeFn<L> + crate::RevTypeFn<R>
{
core::mem::forget(func);
unprojected_type_cmp!{self, L, R, InvokeAlias<F>}
}
/// Maps the type arguments of this `TypeNe`
/// by using the [reversed](crate::RevTypeFn)
/// version of the `F` type-level function.
///
/// Use this function over [`unmap`](Self::unmap)
/// if you want to specify the type of the passed in function explicitly.
///
/// # Example
///
/// ```rust
/// use typewit::{TypeNe, inj_type_fn, type_ne};
///
/// const NE: TypeNe<Option<()>, Option<bool>> = type_ne!(Option<()>, Option<bool>);
///
/// const N3: TypeNe<(), bool> = NE.unproject::<OptionFn>();
///
/// inj_type_fn!{
/// struct OptionFn;
///
/// impl<T> T => Option<T>
/// }
/// ```
pub const fn unproject<F>(
self,
) -> TypeNe<UncallFn<InvokeAlias<F>, L>, UncallFn<InvokeAlias<F>, R>>
where
InvokeAlias<F>: crate::RevTypeFn<L> + crate::RevTypeFn<R>
{
unprojected_type_cmp!{self, L, R, InvokeAlias<F>}
}
/// Maps the `L` and `R` arguments of this `TypeNe<L, R>`
/// back to any argument of the `F` type-level function that would produce them.
///
/// Use this function over [`project_to_arg`](Self::project_to_arg)
/// if you want the type of the passed in function to be inferred.
///
/// This operation is possible because `Call<F, LA> != Call<F, RA>` implies `LA != RA`,
/// i.e.: the return values being different implies that the arguments are different.
///
/// As opposed to [`unmap`](Self::unmap),
/// this only requires `F` to implement [`TypeFn`](crate::TypeFn),
/// and the return type is determined by the caller.
///
/// # Example
///
/// Projecting from item type to collections
///
/// ```rust
/// use typewit::TypeNe;
///
/// use std::ops::{Range, RangeInclusive};
///
/// with_typene(typewit::type_ne!(u8, i8));
///
/// const fn with_typene(ne: TypeNe<u8, i8>) {
/// let _: TypeNe<Vec<u8>, [i8; 1]> = ne.map_to_arg(IntoIterFn);
/// let _: TypeNe<Option<u8>, Result<i8, ()>> = ne.map_to_arg(IntoIterFn);
/// let _: TypeNe<Range<u8>, RangeInclusive<i8>> = ne.map_to_arg(IntoIterFn);
/// }
///
/// typewit::type_fn!{
/// struct IntoIterFn;
///
/// impl<I: IntoIterator> I => I::Item
/// }
/// ```
///
pub const fn map_to_arg<F, LA, RA>(self: TypeNe<L, R>, func: F) -> TypeNe<LA, RA>
where
InvokeAlias<F>: crate::TypeFn<LA, Output = L> + crate::TypeFn<RA, Output = R>
{
core::mem::forget(func);
self.project_to_arg::<F, LA, RA>()
}
/// Maps the `L` and `R` arguments of this `TypeNe<L, R>`
/// back to any argument of the `F` type-level function that would produce them.
///
/// Use this function over [`map_to_arg`](Self::map_to_arg)
/// if you want to specify the type of the passed in function explicitly.
///
/// This operation is possible because `Call<F, LA> != Call<F, RA>` implies `LA != RA`,
/// i.e.: the return values being different implies that the arguments are different.
///
/// As opposed to [`unproject`](Self::unproject),
/// this only requires `F` to implement [`TypeFn`](crate::TypeFn),
/// and the return type is determined by the caller.
///
/// # Example
///
/// Projecting from types to smart pointers that point to them.
///
/// ```rust
/// use typewit::TypeNe;
///
/// use std::sync::Arc;
///
/// with_typene(typewit::type_ne!(str, [u8]));
///
/// const fn with_typene(ne: TypeNe<str, [u8]>) {
/// let _: TypeNe<&str, &[u8]> = ne.project_to_arg::<TargetFn, _, _>();
/// let _: TypeNe<Arc<str>, Box<[u8]>> = ne.project_to_arg::<TargetFn, _, _>();
/// let _: TypeNe<String, Vec<u8>> = ne.project_to_arg::<TargetFn, _, _>();
/// }
///
/// typewit::type_fn!{
/// struct TargetFn;
///
/// impl<I: std::ops::Deref> I => I::Target
/// }
/// ```
///
pub const fn project_to_arg<F, LA, RA>(self: TypeNe<L, R>) -> TypeNe<LA, RA>
where
InvokeAlias<F>: crate::TypeFn<LA, Output = L> + crate::TypeFn<RA, Output = R>
{
// SAFETY: Call<F, LA> != Call<F, RA> implies LA != RA
// (a property fundamental to being a function)
unsafe { TypeNe::new_unchecked() }
}
/// Converts a `TypeNe<L, R>` to `TypeNe<&L, &R>`
///
/// # Example
///
/// ```rust
/// use typewit::{TypeNe, inj_type_fn, type_ne};
///
/// const NE: TypeNe<i32, u32> = type_ne!(i32, u32);
///
/// let foo: i32 = 3;
/// let bar: u32 = 5;
///
/// baz(&foo, &bar, NE.in_ref());
///
/// const fn baz<'a, T, U>(foo: &'a T, bar: &'a U, _ne: TypeNe<&'a T, &'a U>) {
/// // stuff
/// }
/// ```
pub const fn in_ref<'a>(self) -> TypeNe<&'a L, &'a R> {
projected_type_cmp!{self, L, R, crate::type_fn::GRef<'a>}
}
crate::utils::conditionally_const!{
feature = "rust_1_83";
/// Converts a `TypeNe<L, R>` to `TypeNe<&mut L, &mut R>`
///
/// # Constness
///
/// This requires the `"rust_1_83"` feature to be a `const fn`.
///
/// # Example
///
/// ```rust
/// use typewit::{TypeNe, inj_type_fn, type_ne};
///
/// const NE: TypeNe<String, Vec<u8>> = type_ne!(String, Vec<u8>);
///
/// let mut foo: String = "hello".to_string();
/// let mut bar: Vec<u8> = vec![3, 5, 8];
///
/// baz(&mut foo, &mut bar, NE.in_mut());
///
/// fn baz<'a, T, U>(foo: &'a mut T, bar: &'a mut U, _ne: TypeNe<&'a mut T, &'a mut U>) {
/// // stuff
/// }
/// ```
pub fn in_mut['a](self) -> TypeNe<&'a mut L, &'a mut R> {
projected_type_cmp!{self, L, R, crate::type_fn::GRefMut<'a>}
}
}
/// Converts a `TypeNe<L, R>` to `TypeNe<Box<L>, Box<R>>`
///
/// # Example
///
/// ```rust
/// use typewit::{TypeNe, inj_type_fn, type_ne};
///
/// use std::num::{NonZeroI8, NonZeroU8};
///
/// const NE: TypeNe<NonZeroI8, NonZeroU8> = type_ne!(NonZeroI8, NonZeroU8);
///
/// let foo: NonZeroI8 = NonZeroI8::new(-1).unwrap();
/// let bar: NonZeroU8 = NonZeroU8::new(1).unwrap();
///
/// baz(Box::new(foo), Box::new(bar), NE.in_box());
///
/// fn baz<T, U>(foo: Box<T>, bar: Box<U>, _ne: TypeNe<Box<T>, Box<U>>) {
/// // stuff
/// }
/// ```
#[cfg(feature = "alloc")]
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
pub const fn in_box(self) -> TypeNe<Box<L>, Box<R>> {
projected_type_cmp!{self, L, R, crate::type_fn::GBox}
}
}
#[cfg(feature = "rust_1_61")]
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_61")))]
impl<L: Sized, R: Sized> TypeNe<L, R> {
/// Combines `TypeNe<L, R>` and a
/// `O: `[`BaseTypeWitness`]`<L = Usize<UL>, R = Usize<UR>>`
/// into `TypeNe<[L; UL], [R; UR]>`
///
/// [`BaseTypeWitness`]: crate::BaseTypeWitness
///
/// # Example
///
/// ```rust
/// use typewit::{const_marker::Usize, TypeCmp, TypeEq, TypeNe, type_ne};
///
/// const NE: TypeNe<u8, i8> = type_ne!(u8, i8);
///
/// const NE_L: TypeNe<Usize<3>, Usize<5>> = Usize::<3>.equals(Usize::<5>).unwrap_ne();
/// const EQ_L: TypeEq<Usize<8>, Usize<8>> = TypeEq::NEW;
/// const TC_L: TypeCmp<Usize<13>, Usize<21>> = Usize::<13>.equals(Usize::<21>);
///
/// let _: TypeNe<[u8; 3], [i8; 5]> = NE.in_array(NE_L);
/// let _: TypeNe<[u8; 8], [i8; 8]> = NE.in_array(EQ_L);
/// let _: TypeNe<[u8; 13], [i8; 21]> = NE.in_array(TC_L);
///
/// ```
pub const fn in_array<O, const UL: usize, const UR: usize>(
self,
_other: O,
) -> TypeNe<[L; UL], [R; UR]>
where
O: BaseTypeWitness<L = Usize<UL>, R = Usize<UR>>
{
// SAFETY: `TypeNe<L, R>` implies `[L; UL] != [R; UR]`,
// regardless of whether `UL` equals `UR`
unsafe {
TypeNe::new_unchecked()
}
}
}

404
vendor/typewit/src/type_ne_.rs vendored Normal file
View File

@@ -0,0 +1,404 @@
use core::{
any::{Any, TypeId},
cmp::{Ordering, Eq, Ord, PartialEq, PartialOrd},
hash::{Hash, Hasher},
fmt::{self, Debug},
};
use crate::TypeEq;
#[cfg(feature = "rust_1_61")]
use crate::{BaseTypeWitness, SomeTypeArgIsNe};
/// Marker type, for constructing `TypeNe` in [`TypeNe::with_fn`] constructor.
pub enum LeftArg {}
/// Marker type, for constructing `TypeNe` in [`TypeNe::with_fn`] constructor.
pub enum RightArg {}
pub use self::type_ne_::TypeNe;
mod type_ne_ {
use core::marker::PhantomData;
/// Value-level proof that `L` is a different type to `R`
///
/// The opposite of [`TypeEq`](crate::TypeEq).
///
/// # Example
///
/// ```rust
/// use typewit::{const_marker::Usize, TypeNe};
///
/// assert_eq!(
/// array_ref_chunks(&[3, 5, 8, 13, 21, 34, 55], AssertNotZero::V),
/// Chunks {chunks: vec![&[3, 5, 8], &[13, 21, 34]], tail: &[55]}
/// );
///
///
/// fn array_ref_chunks<T, const LEN: usize>(
/// slice: &[T],
/// _not_zero: TypeNe<Usize<LEN>, Usize<0>>,
/// ) -> Chunks<'_, T, LEN> {
/// let mut chunks = slice.chunks_exact(LEN);
///
/// Chunks {
/// chunks: chunks.by_ref().map(|c| <&[T; LEN]>::try_from(c).unwrap()).collect(),
/// tail: chunks.remainder(),
/// }
/// }
///
/// #[derive(Debug, PartialEq, Eq)]
/// struct Chunks<'a, T, const LEN: usize> {
/// chunks: Vec<&'a [T; LEN]>,
/// tail: &'a [T],
/// }
///
/// struct AssertNotZero<const N: usize>;
///
/// impl<const N: usize> AssertNotZero<N> {
/// const V: TypeNe<Usize<N>, Usize<0>> = Usize::<N>.equals(Usize::<0>).unwrap_ne();
/// }
///
/// ```
///
/// If you attempt to pass `0` as the length of the array chunks,
/// you'll get this compile-time error:
/// ```text
/// error[E0080]: evaluation of `main::_doctest_main_src_type_ne_rs_41_0::AssertNotZero::<0>::V` failed
/// --> src/type_ne.rs:71:43
/// |
/// 33 | const V: TypeNe<Usize<N>, Usize<0>> = Usize::<N>.equals(Usize::<0>).unwrap_ne();
/// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'called `TypeCmp::unwrap_ne` on a `TypeEq` value', src/type_ne.rs:33:73
///
/// error[E0080]: erroneous constant used
/// --> src/type_ne.rs:45:50
/// |
/// 7 | array_ref_chunks(&[3, 5, 8, 13, 21, 34, 55], AssertNotZero::<0>::V),
/// | ^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
///
/// ```
pub struct TypeNe<L: ?Sized, R: ?Sized>(PhantomData<TypeNeHelper<L, R>>);
// Declared to work around this error in old Rust versions:
// > error[E0658]: function pointers cannot appear in constant functions
struct TypeNeHelper<L: ?Sized, R: ?Sized>(
#[allow(dead_code)]
fn(PhantomData<L>) -> PhantomData<L>,
#[allow(dead_code)]
fn(PhantomData<R>) -> PhantomData<R>,
);
impl<L: ?Sized, R: ?Sized> TypeNe<L, R> {
/// Constructs a `TypeNe<L, R>`.
///
/// # Safety
///
/// You must ensure that `L != R`.
///
#[inline(always)]
pub const unsafe fn new_unchecked() -> TypeNe<L, R> {
TypeNe(PhantomData)
}
}
}
impl TypeNe<(), ()> {
/// Constructs a `TypeNe` by mapping from a
/// `TypeNe<`[`LeftArg`]`, `[`RightArg`]`>`
/// with an [injective type-level function](crate::InjTypeFn).
///
/// # Alternative
///
/// The [`type_ne`](macro@crate::type_ne) macro can be used as syntactic sugar
/// for calling this constructor with a one-off type-level function.
///
/// # Example
///
/// ```rust
/// use typewit::type_ne::{TypeNe, LeftArg, RightArg};
///
/// const NE: TypeNe<Option<String>, Vec<u16>> = TypeNe::with_fn(MakeNe::NEW);
///
/// typewit::inj_type_fn! {
/// struct MakeNe<T, U>;
///
/// impl LeftArg => Option<T>;
/// impl RightArg => Vec<U>;
/// }
/// ```
pub const fn with_fn<F>(
_func: F,
) -> TypeNe<CallInjFn<InvokeAlias<F>, LeftArg>, CallInjFn<InvokeAlias<F>, RightArg>>
where
InvokeAlias<F>: InjTypeFn<LeftArg> + InjTypeFn<RightArg>
{
core::mem::forget(_func);
// SAFETY: LeftArg isn't RightArg, dummy.
let this: TypeNe<LeftArg, RightArg> = unsafe { TypeNe::new_unchecked() };
projected_type_cmp!{this, LeftArg, RightArg, InvokeAlias<F>}
}
}
impl<L: ?Sized, R: ?Sized> TypeNe<L, R> {
/// Constructs `TypeNe<L, R>` if `L != R`, otherwise returns None.
///
/// # Example
///
/// ```rust
/// use typewit::TypeNe;
///
///
/// let _ne: TypeNe<u8, i8> = TypeNe::with_any().unwrap();
///
/// assert!(TypeNe::<u8, u8>::with_any().is_none());
///
/// ```
#[deprecated = concat!(
"fallout of `https://github.com/rust-lang/rust/issues/97156`,",
"`TypeId::of::<L>() != TypeId::of::<R>()` does not imply `L != R`"
)]
pub fn with_any() -> Option<Self>
where
L: Sized + Any,
R: Sized + Any,
{
if TypeId::of::<L>() != TypeId::of::<R>() {
// SAFETY: unsound for the deprecated reason
unsafe { Some(TypeNe::new_unchecked()) }
} else {
None
}
}
/// Converts this `TypeNe` into a [`TypeCmp`](crate::TypeCmp)
///
/// # Example
///
/// ```rust
/// use typewit::{TypeCmp, TypeNe, type_ne};
///
/// const NE: TypeNe<u8, i8> = type_ne!(u8, i8);
/// const TC: TypeCmp<u8, i8> = NE.to_cmp();
///
/// assert!(matches!(TC, TypeCmp::Ne(_)));
/// ```
#[inline(always)]
pub const fn to_cmp(self) -> crate::TypeCmp<L, R> {
crate::TypeCmp::Ne(self)
}
/// Swaps the type arguments of this `TypeNe`
///
/// # Example
///
/// ```rust
/// use typewit::{TypeNe, type_ne};
///
/// const NE: TypeNe<u8, i8> = type_ne!(u8, i8);
///
/// const N3: TypeNe<i8, u8> = NE.flip();
///
/// ```
pub const fn flip(self: TypeNe<L, R>) -> TypeNe<R, L> {
// SAFETY: type inequality is commutative
unsafe { TypeNe::<R, L>::new_unchecked() }
}
/// Joins a proof of `L != R` with a proof of `J == L`,
/// creating a proof of `J != R`.
///
/// # Example
///
/// ```rust
/// use typewit::{TypeEq, TypeNe, type_ne};
///
/// const NE: TypeNe<str, [u8]> = type_ne!(str, [u8]);
///
/// const fn foo<A: ?Sized>(eq: TypeEq<A, str>) {
/// let _ne: TypeNe<A, [u8]> = NE.join_left(eq);
/// }
/// ```
pub const fn join_left<J: ?Sized>(self: TypeNe<L, R>, _eq: TypeEq<J, L>) -> TypeNe<J, R> {
// SAFETY: (L != R, J == L) implies J != R
unsafe { TypeNe::<J, R>::new_unchecked() }
}
/// Joins a proof of `L != R` with a proof of `R == J`,
/// creating a proof of `L != J`.
///
/// # Example
///
/// ```rust
/// use typewit::{TypeEq, TypeNe, type_ne};
///
/// const NE: TypeNe<String, Vec<u8>> = type_ne!(String, Vec<u8>);
///
/// const fn foo<A>(eq: TypeEq<Vec<u8>, A>) {
/// let _ne: TypeNe<String, A> = NE.join_right(eq);
/// }
/// ```
pub const fn join_right<J: ?Sized>(self: TypeNe<L, R>, _eq: TypeEq<R, J>) -> TypeNe<L, J> {
// SAFETY: (L != R, R == J) implies L != J
unsafe { TypeNe::<L, J>::new_unchecked() }
}
}
#[cfg(feature = "rust_1_61")]
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "rust_1_61")))]
impl<L, R> TypeNe<L, R> {
/// Combines this `TypeNe<L, R>` with an
/// [`A: BaseTypeWitness`](BaseTypeWitness) to produce a
/// `TypeNe<(L, A::L), (R, A::R)>`.
///
/// # Example
///
/// ```rust
/// use typewit::{TypeCmp, TypeEq, TypeNe, type_ne};
///
/// const NE: TypeNe<u8, i8> = type_ne!(u8, i8);
/// const EQ: TypeEq<u16, u16> = TypeEq::NEW;
/// const TC: TypeCmp<u32, u64> = TypeCmp::Ne(type_ne!(u32, u64));
///
/// let _: TypeNe<(u8, i8), (i8, u8)> = NE.zip(NE.flip());
/// let _: TypeNe<(u8, u16), (i8, u16)> = NE.zip(EQ);
/// let _: TypeNe<(u8, u32), (i8, u64)> = NE.zip(TC);
///
/// ```
pub const fn zip<A>(
self: TypeNe<L, R>,
other: A,
) -> TypeNe<(L, A::L), (R, A::R)>
where
A: BaseTypeWitness,
{
SomeTypeArgIsNe::A(TypeEq::NEW).zip2(self, other)
}
/// Combines this `TypeNe<L, R>` with
/// two [`BaseTypeWitness`](BaseTypeWitness)es to produce a
/// `TypeNe<(L, A::L, B::L), (R, A::R, B::R)>`.
///
/// # Example
///
/// ```rust
/// use typewit::{TypeCmp, TypeEq, TypeNe, type_ne};
///
/// const NE: TypeNe<u8, i8> = type_ne!(u8, i8);
/// const EQ: TypeEq<u16, u16> = TypeEq::NEW;
/// const TC: TypeCmp<u32, u64> = TypeCmp::Ne(type_ne!(u32, u64));
///
/// let _: TypeNe<(u8, i8, u8), (i8, u8, i8)> = NE.zip3(NE.flip(), NE);
/// let _: TypeNe<(u8, u16, u16), (i8, u16, u16)> = NE.zip3(EQ, EQ.flip());
/// let _: TypeNe<(u8, u32, u64), (i8, u64, u32)> = NE.zip3(TC, TC.flip());
///
/// ```
pub const fn zip3<A, B>(
self: TypeNe<L, R>,
other1: A,
other2: B,
) -> TypeNe<(L, A::L, B::L), (R, A::R, B::R)>
where
A: BaseTypeWitness,
B: BaseTypeWitness,
A::L: Sized,
A::R: Sized,
{
SomeTypeArgIsNe::A(TypeEq::NEW).zip3(self, other1, other2)
}
/// Combines this `TypeNe<L, R>` with
/// three [`BaseTypeWitness`](BaseTypeWitness)es to produce a
/// `TypeNe<(L, A::L, B::L, C::L), (R, A::R, B::R, C::R)> `.
///
/// # Example
///
/// ```rust
/// use typewit::{TypeCmp, TypeEq, TypeNe, type_ne};
///
/// const NE: TypeNe<u8, i8> = type_ne!(u8, i8);
/// const EQ: TypeEq<u16, u16> = TypeEq::NEW;
/// const TC: TypeCmp<u32, u64> = TypeCmp::Ne(type_ne!(u32, u64));
///
/// let _: TypeNe<(u8, i8, u8, i8), (i8, u8, i8, u8)> = NE.zip4(NE.flip(), NE, NE.flip());
/// let _: TypeNe<(u8, u16, u16, u16), (i8, u16, u16, u16)> = NE.zip4(EQ, EQ.flip(), EQ);
/// let _: TypeNe<(u8, u32, u64, u32), (i8, u64, u32, u64)> = NE.zip4(TC, TC.flip(), TC);
///
/// ```
pub const fn zip4<A, B, C>(
self: TypeNe<L, R>,
other1: A,
other2: B,
other3: C,
) -> TypeNe<(L, A::L, B::L, C::L), (R, A::R, B::R, C::R)>
where
A: BaseTypeWitness,
B: BaseTypeWitness,
C: BaseTypeWitness,
A::L: Sized,
A::R: Sized,
B::L: Sized,
B::R: Sized,
{
SomeTypeArgIsNe::A(TypeEq::NEW).zip4(self, other1, other2, other3)
}
}
// using this instead of `mod extra_type_ne_methods;`
// to document the impls in the submodule below the constructors.
include!{"./type_ne/extra_type_ne_methods.rs"}
impl<L: ?Sized, R: ?Sized> Copy for TypeNe<L, R> {}
impl<L: ?Sized, R: ?Sized> Clone for TypeNe<L, R> {
fn clone(&self) -> Self {
*self
}
}
impl<L: ?Sized, R: ?Sized> Debug for TypeNe<L, R> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("TypeNe")
}
}
impl<L: ?Sized, R: ?Sized> PartialEq for TypeNe<L, R> {
fn eq(&self, _: &Self) -> bool {
true
}
}
impl<L: ?Sized, R: ?Sized> PartialOrd for TypeNe<L, R> {
fn partial_cmp(&self, _: &Self) -> Option<Ordering> {
Some(Ordering::Equal)
}
}
impl<L: ?Sized, R: ?Sized> Ord for TypeNe<L, R> {
fn cmp(&self, _: &Self) -> Ordering {
Ordering::Equal
}
}
impl<L: ?Sized, R: ?Sized> Eq for TypeNe<L, R> {}
impl<L: ?Sized, R: ?Sized> Hash for TypeNe<L, R> {
fn hash<H>(&self, _state: &mut H)
where H: Hasher
{}
}

View File

@@ -0,0 +1,270 @@
#[allow(unused_imports)]
use crate::TypeEq;
use core::marker::PhantomData;
/// Gets a [type witness](crate#what-are-type-witnesses) for `Self`.
///
#[doc = explain_type_witness!()]
///
/// This trait is a helper to write [`W: MakeTypeWitness<Arg = T>`](MakeTypeWitness)
/// with the `T` and `W` type parameters flipped,
/// most useful in supertrait bounds.
///
/// This trait can't be implemented outside of `typewit`.
///
/// # Example
///
/// This example shows how one can make a `const fn` that converts both
/// `&str` and `&[u8]` to `&str`
///
/// (this example requires Rust 1.64.0)
///
#[cfg_attr(not(feature = "rust_stable"), doc = "```ignore")]
#[cfg_attr(feature = "rust_stable", doc = "```rust")]
/// use typewit::{HasTypeWitness, TypeWitnessTypeArg, MakeTypeWitness, TypeEq};
///
/// fn main() {
/// assert_eq!(str_try_from("hello"), Ok("hello"));
///
/// assert_eq!(str_try_from(&[b'w', b'o', b'r', b'l', b'd']), Ok("world"));
///
/// assert_eq!(str_try_from(b"foo bar" as &[_]), Ok("foo bar"));
/// }
///
/// pub const fn str_try_from<'a, T, const L: usize>(
/// input: T
/// ) -> Result<&'a str, std::str::Utf8Error>
/// where
/// T: StrTryFrom<'a, L>
/// {
/// // `T::WITNESS` expands to
/// // `<T as HasTypeWitness<StrTryFromWitness<'a, L, T>>::WITNESS`
/// match T::WITNESS {
/// StrTryFromWitness::Str(te) => {
/// // `te` (a `TypeEq<T, &'a str>`) allows coercing between `T` and `&'a str`.
/// let string: &str = te.to_right(input);
/// Ok(string)
/// }
/// StrTryFromWitness::Bytes(te) => {
/// let bytes: &[u8] = te.to_right(input);
/// std::str::from_utf8(bytes)
/// }
/// StrTryFromWitness::Array(te) => {
/// let slice: &[u8] = te.to_right(input);
/// str_try_from(slice)
/// }
/// }
/// }
///
///
/// // trait alias pattern
/// pub trait StrTryFrom<'a, const L: usize>:
/// Copy + HasTypeWitness<StrTryFromWitness<'a, L, Self>>
/// {}
///
/// impl<'a, T, const L: usize> StrTryFrom<'a, L> for T
/// where
/// T: Copy + HasTypeWitness<StrTryFromWitness<'a, L, T>>
/// {}
///
/// // This macro declares a type witness enum
/// typewit::simple_type_witness! {
/// // Declares `enum StrTryFromWitness<'a, const L: usize, __Wit>`
/// // (the `__Wit` type parameter is implicitly added after all generics)
/// // `#[non_exhausitve]` allows adding more supported types.
/// #[non_exhaustive]
/// pub enum StrTryFromWitness<'a, const L: usize> {
/// // This variant requires `__Wit == &'a str`
/// //
/// // The `<'a, 0>` here changes this macro from generating
/// // `impl<'a, const L: usize> MakeTypeWitness for StrTryFromWitness<'a, L, &'a [u8]>`
/// // to
/// // `impl<'a> MakeTypeWitness for StrTryFromWitness<'a, 0, &'a [u8]>`
/// // which allows the compiler to infer generic arguments when
/// // using the latter `MakeTypeWitness` impl`
/// Str<'a, 0> = &'a str,
///
/// // This variant requires `__Wit == &'a [u8]`
/// Bytes<'a, 0> = &'a [u8],
///
/// // This variant requires `__Wit == &'a [u8; L]`
/// Array = &'a [u8; L],
/// }
/// }
/// ```
pub trait HasTypeWitness<W: TypeWitnessTypeArg<Arg = Self>> {
/// A constant of the type witness
const WITNESS: W;
// prevents dependencies from implementing this trait
#[doc(hidden)]
const __PRIV_KO9Y329U2U: priv_::__Priv<Self, W>;
}
impl<T, W> HasTypeWitness<W> for T
where
T: ?Sized,
W: MakeTypeWitness<Arg = T>,
{
const WITNESS: W = W::MAKE;
#[doc(hidden)]
const __PRIV_KO9Y329U2U: priv_::__Priv<Self, W> = priv_::__Priv(PhantomData, PhantomData);
}
mod priv_ {
use core::marker::PhantomData;
#[doc(hidden)]
pub struct __Priv<T: ?Sized, W>(
pub(super) PhantomData<fn() -> PhantomData<W>>,
pub(super) PhantomData<fn() -> PhantomData<T>>,
);
}
////////////////////////////////////////////////
/// Gets the type argument that this [type witness](crate#what-are-type-witnesses) witnesses.
///
/// [**example shared with `MakeTypeWitness`**](MakeTypeWitness#example)
///
#[doc = explain_type_witness!()]
///
/// This trait should be implemented generically,
/// as generic as the type definition of the implementor,
/// doing so will help type inference.
///
pub trait TypeWitnessTypeArg {
/// The type parameter used for type witnesses.
///
/// Usually, enums that implement this trait have
/// variants with [`TypeEq`]`<`[`Self::Arg`]`, SomeType>` fields.
type Arg: ?Sized;
}
/// Constructs this [type witness](crate#what-are-type-witnesses).
///
#[doc = explain_type_witness!()]
///
/// This trait can be automatically implemented for simple type witnesses
/// by declaring the type witness with the [`simple_type_witness`] macro.
///
/// # Example
///
/// (this example requires Rust 1.61.0)
#[cfg_attr(not(feature = "rust_1_61"), doc = "```ignore")]
#[cfg_attr(feature = "rust_1_61", doc = "```rust")]
/// use typewit::{TypeWitnessTypeArg, MakeTypeWitness, TypeEq};
///
/// const fn default<'a, T, const L: usize>() -> T
/// where
/// Defaultable<'a, L, T>: MakeTypeWitness
/// {
/// match MakeTypeWitness::MAKE {
/// // `te` is a `TypeEq<T, i32>`, which allows coercing between `T` and `i32`.
/// // `te.to_left(...)` goes from `i32` to `T`.
/// Defaultable::I32(te) => te.to_left(3),
///
/// // `te` is a `TypeEq<T, bool>`
/// Defaultable::Bool(te) => te.to_left(true),
///
/// // `te` is a `TypeEq<T, &'a str>`
/// Defaultable::Str(te) => te.to_left("empty"),
///
/// // `te` is a `TypeEq<T, [u32; L]>`
/// Defaultable::Array(te) => te.to_left([5; L]),
/// }
/// }
///
/// let number: i32 = default();
/// assert_eq!(number, 3);
///
/// let boolean: bool = default();
/// assert_eq!(boolean, true);
///
/// let string: &str = default();
/// assert_eq!(string, "empty");
///
/// let array: [u32; 3] = default();
/// assert_eq!(array, [5, 5, 5]);
///
///
/// // This enum is a type witness (documented in the root module)
/// #[non_exhaustive]
/// enum Defaultable<'a, const L: usize, T> {
/// // This variant requires `T == i32`
/// I32(TypeEq<T, i32>),
///
/// // This variant requires `T == bool`
/// Bool(TypeEq<T, bool>),
///
/// // This variant requires `T == &'a str`
/// Str(TypeEq<T, &'a str>),
///
/// // This variant requires `T == [u32; L]`
/// Array(TypeEq<T, [u32; L]>),
/// }
///
/// impl<T, const L: usize> TypeWitnessTypeArg for Defaultable<'_, L, T> {
/// // this aids type inference for what type parameter is witnessed
/// type Arg = T;
/// }
///
/// // Specifying dummy values for the generics that the `I32` variant doesn't use,
/// // so that they don't have to be specified when this impl is used.
/// impl MakeTypeWitness for Defaultable<'_, 0, i32> {
/// // The `TypeEq<T, i32>` field can be constructed because `T == i32` here.
/// const MAKE: Self = Self::I32(TypeEq::NEW);
/// }
///
/// impl MakeTypeWitness for Defaultable<'_, 0, bool> {
/// const MAKE: Self = Self::Bool(TypeEq::NEW);
/// }
///
/// impl<'a> MakeTypeWitness for Defaultable<'a, 0, &'a str> {
/// const MAKE: Self = Self::Str(TypeEq::NEW);
/// }
///
/// impl<const L: usize> MakeTypeWitness for Defaultable<'_, L, [u32; L]> {
/// const MAKE: Self = Self::Array(TypeEq::NEW);
/// }
///
/// ```
///
/// The `Defaultable` type definition and its impls can also be written using
/// the [`simple_type_witness`] macro:
#[cfg_attr(not(feature = "rust_1_61"), doc = "```ignore")]
#[cfg_attr(feature = "rust_1_61", doc = "```rust")]
/// typewit::simple_type_witness!{
/// // Declares `enum Defaultable<'a, const L: usize, __Wit>`
/// // The `__Wit` type parameter is implicit and always the last generic parameter.
/// #[non_exhaustive]
/// enum Defaultable<'a, const L: usize> {
/// // `<'a, 0>` is necessary to have
/// // `impl MakeTypeWitness for Defaultable<'_, 0, i32>` instead of
/// // `impl<'a, const L: u32> MakeTypeWitness for Defaultable<'a, L, i32>`,
/// // which allows the generic arguments to be inferred.
/// I32<'a, 0> = i32,
///
/// Bool<'a, 0> = bool,
///
/// Str<'a, 0> = &'a str,
///
/// Array = [u32; L],
/// }
/// }
/// ```
/// note that [`simple_type_witness`] can't replace enums whose
/// witnessed type parameter is not the last,
/// or have variants with anything but one [`TypeEq`] field each.
///
///
/// [`simple_type_witness`]: crate::simple_type_witness
pub trait MakeTypeWitness: TypeWitnessTypeArg {
/// A constant with the type witness
const MAKE: Self;
}

43
vendor/typewit/src/utils.rs vendored Normal file
View File

@@ -0,0 +1,43 @@
use core::mem::ManuallyDrop;
#[repr(C)]
pub union Transmuter<F, T> {
pub from: ManuallyDrop<F>,
pub to: ManuallyDrop<T>,
}
#[macro_export]
#[doc(hidden)]
macro_rules! __priv_transmute {
($from:ty, $to:ty, $value:expr) => {{
$crate::__::ManuallyDrop::into_inner(
$crate::utils::Transmuter::<$from, $to> {
from: $crate::__::ManuallyDrop::new($value),
}
.to,
)
}};
}
macro_rules! conditionally_const {
(
feature = $feature:literal;
$( #[$meta:meta] )*
$vis:vis fn $fn_name:ident $([$($generics:tt)*])? (
$($params:tt)*
) -> $ret:ty
$block:block
) => (
$(#[$meta])*
#[cfg(feature = $feature)]
$vis const fn $fn_name $(<$($generics)*>)? ($($params)*) -> $ret $block
$(#[$meta])*
#[cfg(not(feature = $feature))]
$vis fn $fn_name $(<$($generics)*>)? ($($params)*) -> $ret $block
)
} pub(crate) use conditionally_const;