-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtype_identity.rs
81 lines (77 loc) · 2.2 KB
/
type_identity.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
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;
}