Skip to content

Instantly share code, notes, and snippets.

Created September 19, 2015 13:21
Show Gist options
  • Save anonymous/d3cbbd1dc9248e5c63bb to your computer and use it in GitHub Desktop.
Save anonymous/d3cbbd1dc9248e5c63bb to your computer and use it in GitHub Desktop.
Shared via Rust Playground
#![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