1#![no_std]
5
6use core::any::TypeId;
7use core::mem::transmute;
8
9#[inline(always)]
11pub fn is_same<T: 'static, U: 'static>() -> bool {
12 TypeId::of::<T>() == TypeId::of::<U>()
13}
14
15#[track_caller]
17#[inline(always)]
18pub fn assert_same<T: 'static, U: 'static>() {
19 assert_eq!(TypeId::of::<T>(), TypeId::of::<U>());
20}
21
22pub trait Coerce<U> {
48 fn coerce(self) -> U;
49}
50
51impl<'a, T: 'static, U: 'static> Coerce<&'a U> for &'a T {
52 #[inline(always)]
53 #[track_caller]
54 fn coerce(self) -> &'a U {
55 assert_same::<T, U>();
56 unsafe { transmute(self) }
57 }
58}
59
60impl<'a, T: 'static, U: 'static> Coerce<&'a mut U> for &'a mut T {
61 #[inline(always)]
62 #[track_caller]
63 fn coerce(self) -> &'a mut U {
64 assert_same::<T, U>();
65 unsafe { transmute(self) }
66 }
67}
68
69impl<'a, T: 'static, U: 'static> Coerce<&'a [U]> for &'a [T] {
70 #[inline(always)]
71 #[track_caller]
72 fn coerce(self) -> &'a [U] {
73 assert_same::<T, U>();
74 unsafe { transmute(self) }
75 }
76}
77
78impl<'a, T: 'static, U: 'static> Coerce<&'a mut [U]> for &'a mut [T] {
79 #[inline(always)]
80 #[track_caller]
81 fn coerce(self) -> &'a mut [U] {
82 assert_same::<T, U>();
83 unsafe { transmute(self) }
84 }
85}
86
87#[inline(always)]
89pub fn coerce<T: Coerce<U>, U>(value: T) -> U {
90 value.coerce()
91}
92
93#[inline(always)]
95pub fn coerce_static<T: 'static, U: 'static>(value: T) -> U {
96 assert_same::<T, U>();
97 unsafe { core::mem::transmute_copy(&core::mem::ManuallyDrop::new(value)) }
98}
99
100#[cfg(test)]
101mod tests {
102 use super::*;
103
104 #[test]
105 fn test_coerce() {
106 let mut ints = [0, 1, 2u32];
107 let mut floats = [0.0, 1.0, 2.0f64];
108
109 pub fn generic_fn<T: 'static>(factor: T, slice: &mut [T]) {
110 if is_same::<u32, T>() {
111 let slice: &mut [u32] = slice.coerce();
112 let factor: u32 = coerce_static(factor);
113 for x in slice {
114 *x = 2 * factor * *x;
115 }
116 } else if is_same::<f64, T>() {
117 let slice: &mut [f64] = slice.coerce();
118 let factor: f64 = coerce_static(factor);
119 for x in slice {
120 *x = factor * *x;
121 }
122 }
123 }
124
125 generic_fn(2, &mut ints);
126 generic_fn(2.0, &mut floats);
127
128 assert_eq!(ints, [0, 4, 8]);
129 assert_eq!(floats, [0.0, 2.0, 4.0]);
130 }
131}