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;