Created
September 19, 2015 13:21
-
-
Save anonymous/d3cbbd1dc9248e5c63bb to your computer and use it in GitHub Desktop.
Shared via Rust Playground
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(unsize)] | |
| #![feature(raw)] | |
| #![feature(const_fn)] | |
| use std::marker::{Unsize, PhantomData}; | |
| use std::fmt::Display; | |
| use std::fmt::Debug; | |
| use std::raw::TraitObject; | |
| use std::cell::Cell; | |
| use std::mem; | |
| use std::ops::Deref; | |
| trait Dst: Unsize<Self> {} | |
| impl<T: ?Sized + Unsize<T>> Dst for T {} | |
| type Meta = *const (); | |
| #[repr(C)] | |
| struct MetaField<D: ?Sized + Dst, T: ?Sized = D> { | |
| meta: Cell<Meta>, | |
| _marker: PhantomData<Cell<*const D>>, | |
| data: T, | |
| } | |
| impl<D: ?Sized + Dst, T> MetaField<D, T> { | |
| const fn new(t: T) -> MetaField<D, T> { | |
| MetaField { | |
| meta: Cell::new(0 as *const _), | |
| data: t, | |
| _marker: PhantomData, | |
| } | |
| } | |
| } | |
| impl<D: ?Sized + Dst, T: ?Sized> 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> MetaPrefix<D> for MetaField<D, T> {} | |
| unsafe trait Unaliased {} | |
| unsafe impl<T: ?Sized> Unaliased for Box<T> {} | |
| unsafe impl<'a, T: ?Sized> Unaliased for &'a mut T {} | |
| struct Thin<'a, T: ?Sized + 'a> { | |
| data: &'a (), | |
| _marker: PhantomData<&'a T>, | |
| } | |
| impl<'a, T: ?Sized + Dst> Thin<'a, T> { | |
| fn new(dst: &T) -> Thin<T> | |
| { | |
| unsafe { | |
| let p: *const &T = &dst; | |
| let p = p as *const TraitObject; | |
| let dst = *p; | |
| let meta_ref: &Cell<Meta> = &*(dst.data as *const _); | |
| meta_ref.set(dst.vtable); | |
| Thin { | |
| data: &*(dst.data as *const _), | |
| _marker: PhantomData, | |
| } | |
| } | |
| } | |
| } | |
| impl<'a, T: ?Sized> Deref for Thin<'a, T> { | |
| type Target = T; | |
| fn deref(&self) -> &T { | |
| unsafe { | |
| let meta: &Cell<Meta> = &*(self.data as *const _ as *const _); | |
| let meta = meta.get(); | |
| let trait_object = TraitObject { | |
| data: self.data as *const _ as *mut _, | |
| vtable: meta as *const _ as *mut _, | |
| }; | |
| let p: *const TraitObject = &trait_object; | |
| let p: *const *const TraitObject = &p; | |
| let p: *const *const &T = p as *const _; | |
| **p | |
| } | |
| } | |
| } | |
| //////////////////////////////////////////////////////////////////////////////// | |
| struct DstWrap<T: ?Sized> { | |
| _stuff: [u64; 3], | |
| _t: T, | |
| } | |
| static mut X: MetaField<Display, i32> = MetaField::new(5); | |
| static mut Y: MetaField<DstWrap<Display>, DstWrap<i32>> = MetaField::new(DstWrap { _stuff: [0,0,0], _t: 10 }); | |
| fn main() { | |
| // 'static default prevents creating these borrowed DST on the stack. | |
| let x: &MetaField<_> = unsafe { &X }; | |
| let y: &MetaField<_> = unsafe { &Y }; | |
| println!("size_of x: {} display: {}", mem::size_of_val(&x), &**x); | |
| println!("size_of y: {}", mem::size_of_val(&y)); | |
| let x_thin: Thin<MetaField<Display>> = Thin::new(x); | |
| let y_thin: Thin<MetaField<DstWrap<Display>>> = Thin::new(y); | |
| 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)); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment