core_extensions/type_identity.rs
1use std_::mem;
2
3#[cfg(feature = "alloc")]
4use alloc::{
5 boxed::Box,
6 rc::Rc,
7 sync::Arc,
8};
9
10use crate::utils::{self, transmute_ignore_size};
11
12/// Allows converting `Self` to
13/// [`Self::Type`](./trait.TypeIdentity.html#associatedtype.Type)
14/// by proving that both types are equal.
15///
16/// # Usecases
17///
18/// This trait allows:
19///
20/// - Defining extension traits without repeating method signatures.
21///
22/// - Creating a type Alias in a where clause, eg: `Vec<i32>: TypeIdentity<Type = List>`.
23///
24/// - Unwrapping a generic type, eg: `I: TypeIdentity<Type = Option<U>>`.
25///
26/// # Example
27///
28/// Defining an extension trait on `Vec<T>`.
29///
30/// ```
31/// use core_extensions::TypeIdentity;
32///
33/// trait VecExt<T>: TypeIdentity<Type = Vec<T>> + Sized {
34/// fn is_nonempty(&self) -> bool {
35/// !self.as_type().is_empty()
36/// }
37///
38/// fn moved_vec(self) -> Vec<T> {
39/// self.into_type()
40/// }
41///
42/// fn mutable_vec(&mut self) -> &mut Vec<T> {
43/// self.as_type_mut()
44/// }
45/// }
46/// impl<T> VecExt<T> for Vec<T> {}
47///
48/// assert!( vec![100].is_nonempty());
49/// assert!(!Vec::<i32>::new().is_nonempty());
50/// ```
51///
52///
53///
54///
55/// # Example of a method requiring `Self == Other`
56///
57/// `Wrapper::iter` is only callable on `Wrapper<Vec<T>>`
58///
59/// ```
60/// use core_extensions::TypeIdentity;
61///
62/// use std::slice;
63///
64/// struct Wrapper<U>(U);
65///
66/// impl<U> Wrapper<U> {
67/// fn iter<T>(&self) -> slice::Iter<T>
68/// where U: TypeIdentity<Type = Vec<T>>
69/// {
70/// self.0.as_type().iter()
71/// }
72/// }
73///
74/// assert_eq!(
75/// Wrapper(vec![0, 1, 2, 3, 4]).iter().cloned().collect::<Vec<_>>(),
76/// vec![0, 1, 2, 3, 4]
77/// );
78///
79/// ```
80///
81///
82/// # Example of creating a type alias in a `where` clause
83///
84/// ```rust
85/// use core_extensions::TypeIdentity;
86///
87/// use std::ops::Deref;
88///
89/// struct Example<T>(T);
90///
91/// impl<T, Target0, Target1> Deref for Example<T>
92/// where
93/// T: Deref,
94/// <T as Deref>::Target: TypeIdentity<Type = Target0>,
95/// Target0: Deref,
96/// <Target0 as Deref>::Target: TypeIdentity<Type = Target1>,
97/// {
98/// type Target = Target1;
99///
100/// fn deref(&self) -> &Target1 {
101/// &**self
102/// }
103/// }
104///
105/// ```
106///
107///
108#[cfg_attr(feature = "docsrs", doc(cfg(feature = "type_identity")))]
109pub trait TypeIdentity {
110 /// This is always `Self`.
111 type Type: ?Sized;
112
113 /// Converts a value back to the original type.
114 #[inline(always)]
115 fn into_type(self) -> Self::Type
116 where
117 Self: Sized,
118 Self::Type: Sized,
119 {
120 unsafe { transmute_ignore_size(self) }
121 }
122 /// Converts a reference back to the original type.
123 #[inline(always)]
124 fn as_type(&self) -> &Self::Type {
125 unsafe { mem::transmute_copy::<&Self, &Self::Type>(&self) }
126 }
127 /// Converts a mutable reference back to the original type.
128 #[inline(always)]
129 fn as_type_mut(&mut self) -> &mut Self::Type {
130 unsafe { mem::transmute_copy::<&mut Self, &mut Self::Type>(&self) }
131 }
132 /// Converts a box back to the original type.
133 #[cfg(feature = "alloc")]
134 #[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
135 #[inline(always)]
136 fn into_type_box(self: Box<Self>) -> Box<Self::Type> {
137 unsafe { utils::transmute_ignore_size(self) }
138 }
139
140 if_rust_1_46!{
141 /// Converts an Arc back to the original type.
142 ///
143 /// # Self parameter
144 ///
145 /// Enabling the "rust_1_46" feature changes this method from
146 /// taking a `this` parameter to taking a`self` parameter,
147 /// which allows calling it with `.into_type_arc()`
148 ///
149 #[cfg(feature = "alloc")]
150 #[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
151 #[inline(always)]
152 =>
153 (
154 fn into_type_arc(this: Arc<Self>) -> Arc<Self::Type> {
155 unsafe { utils::transmute_ignore_size(this) }
156 }
157 )
158 (
159 fn into_type_arc(self: Arc<Self>) -> Arc<Self::Type> {
160 unsafe { utils::transmute_ignore_size(self) }
161 }
162 )
163 }
164
165 if_rust_1_46!{
166 /// Converts an Rc back to the original type.
167 ///
168 /// # Self parameter
169 ///
170 /// Enabling the "rust_1_46" feature changes this method from
171 /// taking a `this` parameter to taking a`self` parameter,
172 /// which allows calling it with `.into_type_rc()`
173 ///
174 #[cfg(feature = "alloc")]
175 #[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
176 #[inline(always)]
177 =>
178 (
179 fn into_type_rc(this: Rc<Self>) -> Rc<Self::Type> {
180 unsafe { utils::transmute_ignore_size(this) }
181 }
182 )
183 (
184 fn into_type_rc(self: Rc<Self>) -> Rc<Self::Type> {
185 unsafe { utils::transmute_ignore_size(self) }
186 }
187 )
188 }
189
190
191 /// Converts a value back to the original type.
192 #[inline(always)]
193 fn from_type(this: Self::Type) -> Self
194 where
195 Self: Sized,
196 Self::Type: Sized,
197 {
198 let this = mem::ManuallyDrop::new(this);
199 unsafe { mem::transmute_copy::<Self::Type, Self>(&*this) }
200 }
201 /// Converts a reference back to the original type.
202 #[inline(always)]
203 fn from_type_ref(this: &Self::Type) -> &Self {
204 unsafe { mem::transmute_copy::<&Self::Type, &Self>(&this) }
205 }
206 /// Converts a mutable reference back to the original type.
207 #[inline(always)]
208 fn from_type_mut(this: &mut Self::Type) -> &mut Self {
209 unsafe { mem::transmute_copy::<&mut Self::Type, &mut Self>(&this) }
210 }
211 /// Converts a box back to the original type.
212 #[cfg(feature = "alloc")]
213 #[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
214 #[inline(always)]
215 fn from_type_box(this: Box<Self::Type>) -> Box<Self> {
216 unsafe { utils::transmute_ignore_size(this) }
217 }
218 /// Converts an Arc back to the original type.
219 #[cfg(feature = "alloc")]
220 #[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
221 #[inline(always)]
222 fn from_type_arc(this: Arc<Self::Type>) -> Arc<Self> {
223 unsafe { utils::transmute_ignore_size(this) }
224 }
225 /// Converts an Rc back to the original type.
226 #[cfg(feature = "alloc")]
227 #[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
228 #[inline(always)]
229 fn from_type_rc(this: Rc<Self::Type>) -> Rc<Self> {
230 unsafe { utils::transmute_ignore_size(this) }
231 }
232
233 #[doc(hidden)]
234 #[allow(dead_code)]
235 /// Prevents creating a trait object of this trait
236 fn _dummy_generic_method_preventing_trait_object<F>(self: &Self)
237 where
238 F: TypeIdentity<Type = Self>,
239 {
240
241 }
242}
243
244impl<T: ?Sized> TypeIdentity for T {
245 type Type = T;
246}
247
248/// A type-level identity function
249#[cfg_attr(feature = "docsrs", doc(cfg(feature = "type_identity")))]
250pub type TIdentity<Type> = <Type as TypeIdentity>::Type;