diff --git a/src/lifetime_expansion.rs b/src/lifetime_expansion.rs
index 867b643..fc1b6ca 100644
--- a/src/lifetime_expansion.rs
+++ b/src/lifetime_expansion.rs
@@ -30,7 +30,6 @@ pub const fn lifetime_translator<'a, 'b, T>(_val_a: &'a &'b (), val_b: &'b T) ->
}
/// This does the same thing as [`lifetime_translator`], just for mutable refs.
-#[inline(never)]
pub fn lifetime_translator_mut<'a, 'b, T>(_val_a: &'a &'b (), val_b: &'b mut T) -> &'a mut T {
val_b
}
diff --git a/src/transmute.rs b/src/transmute.rs
index 2d12261..572cef9 100644
--- a/src/transmute.rs
+++ b/src/transmute.rs
@@ -22,9 +22,8 @@
/// # Safety
/// lol
///
+#[allow(unused_assignments)]
pub fn transmute(obj: A) -> B {
- use std::hint::black_box;
-
// The layout of `DummyEnum` is approximately
// DummyEnum {
// is_a_or_b: u8,
@@ -34,23 +33,22 @@ pub fn transmute(obj: A) -> B {
// This should hopefully be more reliable than spamming the stack with a value and hoping the memory
// is placed correctly by the compiler.
enum DummyEnum {
- A(Option>),
- B(Option>),
+ A(Result>>),
+ B(Result>>),
}
- #[inline(never)]
- fn transmute_inner(dummy: &mut DummyEnum, 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()
+ union Blank {
+ _a: std::mem::ManuallyDrop,
+ _b: std::mem::ManuallyDrop,
}
- transmute_inner(black_box(&mut DummyEnum::B(None)), obj)
+ let mut res = DummyEnum::B(Err(None));
+ let DummyEnum::B(ref_to_b) = &mut res else {
+ unreachable!()
+ };
+ let ref_to_b = crate::lifetime_expansion::expand_mut(ref_to_b);
+ res = DummyEnum::A(Ok(obj));
+ std::mem::replace(ref_to_b, Err(None)).ok().unwrap()
}
#[cfg(test)]