Skip to content

Instantly share code, notes, and snippets.

@Centril
Created January 4, 2017 09:56
Show Gist options
  • Save Centril/befe7ed7aa11af68309413f97f27af62 to your computer and use it in GitHub Desktop.
Save Centril/befe7ed7aa11af68309413f97f27af62 to your computer and use it in GitHub Desktop.
fn to_rc<T: ?Sized>(b: Box<T>) -> Rc<T>
#![feature(alloc, heap_api)]
extern crate alloc;
use std::rc::Rc;
use std::mem::{align_of, align_of_val, size_of, size_of_val};
fn to_rc<T: ?Sized>(b: Box<T>) -> Rc<T> {
// super duper undefined behavior!
struct InnerRcBox<T: ?Sized> {
strong: usize,
weak: usize,
t: T,
}
struct InnerRc<T: ?Sized> {
ptr: *mut InnerRcBox<T>,
}
let size = size_of_val(&*b);
let align = align_of_val(&*b);
unsafe {
let ret_ptr = alloc::heap::allocate(
size + 2 * size_of::<usize>(),
if align > align_of::<usize>() { align } else { align_of::<usize>() },
);
*ret_ptr = 1; // strong
*ret_ptr.offset(1) = 1; // weak
std::ptr::copy_nonoverlapping(
&*b as *const _ as *const u8,
ret_ptr.offset(2) as *mut u8,
size,
);
let mut ret = std::mem::transmute::<Box<T>, InnerRc<T>>(b);
// UB alert - assume that DST pointers are laid out { ptr, ...rest }
let ptr_to_ptr = &mut ret.ptr as *mut *mut InnerRcBox<T> as *mut *mut u8;
let original_box_ptr = std::mem::replace(&mut *ptr_to_ptr, ret_ptr);
alloc::heap::deallocate(
original_box_ptr as *mut u8,
size,
align,
);
// UB alert - transmuting between rerp(Rust)
std::mem::transmute::<InnerRc<T>, Rc<T>>(ret)
}
}
fn main(){}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment