Skip to content

Instantly share code, notes, and snippets.

@Kimundi
Forked from anonymous/playground.rs
Created September 19, 2015 11:49
Show Gist options
  • Save Kimundi/b74fb36bfd4bbaa75e50 to your computer and use it in GitHub Desktop.
Save Kimundi/b74fb36bfd4bbaa75e50 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::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 ();
unsafe trait MetaPrefix {}
#[repr(C)]
struct MetaField<T: ?Sized> {
meta: Cell<Meta>,
data: T,
}
impl<T> MetaField<T> {
const fn new(t: T) -> MetaField<T> {
MetaField {
meta: Cell::new(0 as *const _),
data: t,
}
}
}
unsafe impl<T: ?Sized> MetaPrefix for MetaField<T> {}
impl<T: ?Sized> Deref for MetaField<T> {
type Target = T;
fn deref(&self) -> &T {
&self.data
}
}
struct Thin<'a, T: ?Sized + 'a> {
data: &'a (),
_marker: PhantomData<&'a T>,
}
impl<'a, T: ?Sized + Dst + MetaPrefix> 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<i32> = MetaField::new(5);
static mut Y: MetaField<DstWrap<i32>> = MetaField::new(DstWrap { _stuff: [0,0,0], _t: 10 });
fn main() {
// Some bug prevents creating these borrowed DST on the stack right now.
let x: &MetaField<Display> = unsafe { &X };
let y: &MetaField<DstWrap<Display>> = 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::new(x);
let y_thin = 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