pub fn transmute<A, B>(obj: A) -> B {
use std::hint::black_box;
#[allow(dead_code)]
enum DummyEnum<A, B> {
A(Option<Box<A>>),
B(Option<Box<B>>),
}
#[inline(never)]
fn transmute_inner<A, B>(dummy: &mut DummyEnum<A, B>, obj: A) -> B {
let DummyEnum::B(ref_to_b) = dummy else {
unreachable!()
};
let ref_to_b = crate::lifetime_expansion::expand_mut(ref_to_b);
*dummy = DummyEnum::A(Some(Box::new(obj)));
black_box(dummy);
*ref_to_b.take().unwrap()
}
transmute_inner(black_box(&mut DummyEnum::B(None)), obj)
}
#[cfg(test)]
mod tests {
#![allow(unsafe_code)]
#[test]
#[allow(clippy::transmute_float_to_int, clippy::transmute_num_to_bytes)]
fn test_transmute() {
use crate::transmute;
use std::mem;
unsafe {
assert_eq!(
transmute::transmute::<f32, i32>(420.69),
mem::transmute::<f32, i32>(420.69)
);
assert_eq!(
transmute::transmute::<u32, i32>(0xf0000000),
mem::transmute::<u32, i32>(0xf0000000)
);
assert_eq!(
transmute::transmute::<f64, [u8; 8]>(123.456),
mem::transmute::<f64, [u8; 8]>(123.456)
);
let my_ref = &42;
assert_eq!(
transmute::transmute::<&u8, isize>(my_ref),
mem::transmute::<&u8, isize>(my_ref)
);
assert_eq!(
transmute::transmute::<[i32; 5], [u8; 20]>([1, 2, 3, 4, 5]),
mem::transmute::<[i32; 5], [u8; 20]>([1, 2, 3, 4, 5])
);
assert_eq!(
transmute::transmute::<bool, u8>(true),
mem::transmute::<bool, u8>(true)
);
}
}
}