-
-
Save Kimundi/b74fb36bfd4bbaa75e50 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::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