Created
September 19, 2015 15:44
-
-
Save anonymous/2db3cda86bfccf16a673 to your computer and use it in GitHub Desktop.
Shared via Rust Playground
This file contains 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(unsize)] | |
#![feature(raw)] | |
#![feature(const_fn)] | |
#![feature(unique)] | |
use std::marker::{Unsize, PhantomData}; | |
use std::fmt::Display; | |
use std::raw::TraitObject; | |
use std::mem; | |
use std::ops::Deref; | |
use std::rc::Rc; | |
use std::sync::Arc; | |
trait Dst: Unsize<Self> {} | |
impl<T: ?Sized + Unsize<T>> Dst for T {} | |
type Meta = usize; | |
#[repr(C)] | |
struct MetaField<D: ?Sized + Dst, T: ?Sized + Unsize<D> = D> { | |
meta: Meta, | |
_marker: PhantomData<ptr::Unique<D>>, | |
data: T, | |
} | |
impl<D: ?Sized + Dst, T: Unsize<D>> MetaField<D, T> { | |
fn new(t: T) -> MetaField<D, T> { | |
MetaField { | |
meta: unsafe { | |
super_transmute::<*const D, TraitObject>(&t as &D).vtable as usize | |
}, | |
data: t, | |
_marker: PhantomData, | |
} | |
} | |
} | |
impl<D: ?Sized + Dst, T: ?Sized + Unsize<D>> Deref for MetaField<D, T> { | |
type Target = T; | |
fn deref(&self) -> &T { | |
&self.data | |
} | |
} | |
unsafe trait MetaPrefix<D: ?Sized + Dst> {} | |
unsafe impl<D: ?Sized + Dst, T: ?Sized + Unsize<D>> MetaPrefix<D> for MetaField<D, T> {} | |
unsafe trait Ptr: Sized + Deref { | |
type Erased: Ptr; | |
unsafe fn erase(self) -> Self::Erased | |
{ | |
let this = super_transmute::<Self, TraitObject>(self); | |
super_transmute(this.data) | |
} | |
unsafe fn unerase<T>(self, meta: Meta) -> T { | |
let this = TraitObject { | |
data: super_transmute(self), | |
vtable: super_transmute(meta), | |
}; | |
super_transmute(this) | |
} | |
unsafe fn as_unerased<T: ?Sized + Dst>(&self, meta: Meta) -> &T { | |
let this = TraitObject { | |
data: super_transmute(&**self), | |
vtable: super_transmute(meta), | |
}; | |
super_transmute(this) | |
} | |
} | |
unsafe impl<'a, T: ?Sized> Ptr for &'a T { type Erased = &'a (); } | |
unsafe impl<'a, T: ?Sized> Ptr for &'a mut T { type Erased = &'a mut (); } | |
unsafe impl<T: ?Sized> Ptr for Box<T> { type Erased = Box<()>; } | |
unsafe impl<T: ?Sized> Ptr for Rc<T> { type Erased = Rc<()>; } | |
unsafe impl<T: ?Sized> Ptr for Arc<T> { type Erased = Arc<()>; } | |
struct Thin<P: Ptr> | |
where P::Erased: Deref<Target = ()> | |
{ | |
data: P::Erased, | |
_marker: PhantomData<P>, | |
} | |
impl<P: Ptr> Thin<P> | |
where P::Erased: Deref<Target = ()>, | |
P::Target: Dst, | |
{ | |
fn new(dst: P) -> Thin<P> | |
{ | |
unsafe { | |
Thin { | |
data: dst.erase(), | |
_marker: PhantomData, | |
} | |
} | |
} | |
} | |
impl<P: Ptr + Deref> Deref for Thin<P> | |
where P::Erased: Deref<Target = ()>, | |
P::Target: Dst, | |
{ | |
type Target = P::Target; | |
fn deref(&self) -> &Self::Target { | |
unsafe { | |
let meta = *super_transmute::<&(), &Meta>(&*self.data); | |
self.data.as_unerased(meta) | |
} | |
} | |
} | |
use std::ptr; | |
unsafe fn super_transmute<T, U>(t: T) -> U { | |
let u: U = mem::transmute_copy(&t); | |
mem::forget(t); | |
u | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
struct DstWrap<T: ?Sized> { | |
_stuff: [u64; 3], | |
_t: T, | |
} | |
fn main() { | |
let x: &MetaField<Display> = &MetaField::new(5); | |
let y: &MetaField<DstWrap<Display>> = &MetaField::new(DstWrap { _stuff: [0,0,0], _t: 10 }); | |
let z: Box<MetaField<Display>> = Box::new(MetaField::new(42)); | |
let rc: Rc<MetaField<Display>> = Rc::new(MetaField::new(64211)); | |
let arc: Arc<MetaField<Display + Send + Sync>> = Arc::new(MetaField::new(98765)); | |
println!("size_of x: {} display: {}", mem::size_of_val(&x), &**x); | |
println!("size_of y: {}", mem::size_of_val(&y)); | |
println!("size_of z: {} display: {}", mem::size_of_val(&z), &**z); | |
println!("size_of rc: {} display: {}", mem::size_of_val(&rc), &**rc); | |
println!("size_of arc: {} display: {}", mem::size_of_val(&arc), &**arc); | |
let x_thin: Thin<&MetaField<Display>> = Thin::new(x); | |
let y_thin: Thin<&MetaField<DstWrap<Display>>> = Thin::new(y); | |
let z_thin: Thin<Box<MetaField<Display>>> = Thin::new(z); | |
let rc_thin: Thin<Rc<MetaField<Display>>> = Thin::new(rc); | |
let arc_thin: Thin<Arc<MetaField<Display + Send + Sync>>> = Thin::new(arc); | |
println!("size_of x_thin: {} display {}", mem::size_of_val(&x_thin), &**x_thin); | |
println!("size_of y_thin: {}", mem::size_of_val(&y_thin)); | |
println!("size_of z_thin: {} display {}", mem::size_of_val(&z_thin), &**z_thin); | |
println!("size_of rc_thin: {} display {}", mem::size_of_val(&rc_thin), &**rc_thin); | |
println!("size_of arc_thin: {} display {}", mem::size_of_val(&arc_thin), &**arc_thin); | |
//let k_thin: Thin<Box<MetaField<Display, i32>>> = Thin::new(Box::new(MetaField::new(98))); | |
//println!("size_of k_thin: {} display {}", mem::size_of_val(&k_thin), &**k_thin); | |
fn test_send<T: Send>(_: T) {} | |
test_send(Arc::new(5) as Arc<Display + Send + Sync>); | |
test_send(arc_thin); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment