From 73248114eaf11c0f99f389e138aa2c1930d5ac14 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sun, 16 Sep 2018 11:57:27 +0200 Subject: [PATCH] Implement unsize of adt's (cc #14) --- examples/mini_core.rs | 5 ++++- examples/mini_core_hello_world.rs | 3 ++- src/common.rs | 17 ++++++++++++++++- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/examples/mini_core.rs b/examples/mini_core.rs index 544f2eceac0f..8fa27662bdac 100644 --- a/examples/mini_core.rs +++ b/examples/mini_core.rs @@ -12,6 +12,7 @@ pub trait Unsize {} pub trait CoerceUnsized {} impl<'a, 'b: 'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} +impl, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} #[lang = "copy"] pub unsafe trait Copy {} @@ -203,7 +204,9 @@ pub unsafe fn drop_in_place(to_drop: *mut T) { } #[lang = "owned_box"] -pub struct Box(*mut T); +pub struct Box(*mut T); + +impl, U: ?Sized> CoerceUnsized> for Box {} static mut MY_TINY_HEAP: [u8; 16] = [0; 16]; diff --git a/examples/mini_core_hello_world.rs b/examples/mini_core_hello_world.rs index ff7d7975e276..84651ffd5ff5 100644 --- a/examples/mini_core_hello_world.rs +++ b/examples/mini_core_hello_world.rs @@ -111,8 +111,9 @@ fn main() { // TODO remove when jit supports linking rlibs #[cfg(not(jit))] { - let world = box "World!\0"; + let world: Box<&str> = box "World!\0"; puts(*world as *const str as *const u8); + world as Box; } assert_eq!(intrinsics::size_of_val(hello) as u8, 6); diff --git a/src/common.rs b/src/common.rs index 55cf333bbdc8..3213a94ba23c 100644 --- a/src/common.rs +++ b/src/common.rs @@ -252,7 +252,22 @@ impl<'tcx> CValue<'tcx> { }; dest.write_cvalue(fx, CValue::ByValPair(ptr, extra, dest.layout())); } - ty => unimpl!("unsize of non ptr {:?}", ty), + _ => { + assert!(!self.layout().ty.is_enum(), "Tried to unsize enum"); + let field_count = self.layout().fields.count(); + let mut found_unsize_field = false; + for idx in 0..field_count { + let field_dest = dest.place_field(fx, mir::Field::new(idx)); + let field_src = self.value_field(fx, mir::Field::new(idx)); + if field_src.layout().ty != field_dest.layout().ty { + assert!(!found_unsize_field); + found_unsize_field = true; + field_src.unsize_value(fx, field_dest); + } else { + field_dest.write_cvalue(fx, field_src); + } + } + } } }