Created
January 4, 2017 09:56
-
-
Save Centril/befe7ed7aa11af68309413f97f27af62 to your computer and use it in GitHub Desktop.
fn to_rc<T: ?Sized>(b: Box<T>) -> Rc<T>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![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