about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-09-11 04:55:41 +0000
committerbors <bors@rust-lang.org>2014-09-11 04:55:41 +0000
commit1f4117f5182249d91c52cc3e384e4577356e1634 (patch)
treecfa16e82923ad5048b2bc770296e8b0be6585945
parent7ea660e678434dc1eea2a3b60bf3bc92c8404745 (diff)
parent9639cafd3625429ea558d3202cffdfc851fcf9cf (diff)
downloadrust-1f4117f5182249d91c52cc3e384e4577356e1634.tar.gz
rust-1f4117f5182249d91c52cc3e384e4577356e1634.zip
auto merge of #17110 : thestinger/rust/dst, r=cmr
The pointer in the slice must not be null, because enum representations
make that assumption. The `exchange_malloc` function returns a non-null
sentinel for the zero size case, and it must not be passed to the
`exchange_free` lang item.

Since the length is always equal to the true capacity, a branch on the
length is enough for most types. Slices of zero size types are
statically special cased to never attempt deallocation. This is the same
implementation as `Vec<T>`.

Closes #14395
-rw-r--r--src/liballoc/heap.rs6
-rw-r--r--src/librustc/middle/trans/expr.rs28
-rw-r--r--src/librustc/middle/trans/tvec.rs21
-rw-r--r--src/test/run-pass/empty-allocation-non-null.rs6
4 files changed, 24 insertions, 37 deletions
diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs
index 62010ca8916..c7bc1bb9733 100644
--- a/src/liballoc/heap.rs
+++ b/src/liballoc/heap.rs
@@ -12,7 +12,6 @@
 // FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias`
 //                and `nonnull`
 
-use core::ptr::RawPtr;
 #[cfg(not(test))] use core::raw;
 #[cfg(stage0, not(test))] use util;
 
@@ -70,11 +69,6 @@ pub unsafe fn reallocate_inplace(ptr: *mut u8, size: uint, align: uint,
 /// the value returned by `usable_size` for the requested size.
 #[inline]
 pub unsafe fn deallocate(ptr: *mut u8, size: uint, align: uint) {
-    // FIXME(14395) This is only required for DST ~[T], it should be removed once
-    // we fix that representation to not use null pointers.
-    if ptr.is_null() {
-        return;
-    }
     imp::deallocate(ptr, size, align)
 }
 
diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs
index 67dee371083..bfcf4a11bc2 100644
--- a/src/librustc/middle/trans/expr.rs
+++ b/src/librustc/middle/trans/expr.rs
@@ -412,29 +412,11 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         let vec_ty = ty::mk_uniq(tcx, ty::mk_vec(tcx, unit_ty, None));
         let scratch = rvalue_scratch_datum(bcx, vec_ty, "__unsize_unique");
 
-        if len == 0 {
-            Store(bcx,
-                  C_null(type_of::type_of(bcx.ccx(), unit_ty).ptr_to()),
-                  get_dataptr(bcx, scratch.val));
-        } else {
-            // Box<[(), ..n]> will not allocate, but ~[()] expects an
-            // allocation of n bytes, so we must allocate here (yuck).
-            let llty = type_of::type_of(bcx.ccx(), unit_ty);
-            if llsize_of_alloc(bcx.ccx(), llty) == 0 {
-                let ptr_unit_ty = type_of::type_of(bcx.ccx(), unit_ty).ptr_to();
-                let align = C_uint(bcx.ccx(), 8);
-                let alloc_result = malloc_raw_dyn(bcx, ptr_unit_ty, vec_ty, ll_len, align);
-                bcx = alloc_result.bcx;
-                let base = get_dataptr(bcx, scratch.val);
-                Store(bcx, alloc_result.val, base);
-            } else {
-                let base = get_dataptr(bcx, scratch.val);
-                let base = PointerCast(bcx,
-                                       base,
-                                       type_of::type_of(bcx.ccx(), datum_ty).ptr_to());
-                bcx = lval.store_to(bcx, base);
-            }
-        }
+        let base = get_dataptr(bcx, scratch.val);
+        let base = PointerCast(bcx,
+                               base,
+                               type_of::type_of(bcx.ccx(), datum_ty).ptr_to());
+        bcx = lval.store_to(bcx, base);
 
         Store(bcx, ll_len, get_len(bcx, scratch.val));
         DatumBlock::new(bcx, scratch.to_expr_datum())
diff --git a/src/librustc/middle/trans/tvec.rs b/src/librustc/middle/trans/tvec.rs
index 00b9977c752..c0d19b31cb8 100644
--- a/src/librustc/middle/trans/tvec.rs
+++ b/src/librustc/middle/trans/tvec.rs
@@ -72,14 +72,19 @@ pub fn make_drop_glue_unboxed<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         };
 
         if should_deallocate {
-            let not_null = IsNotNull(bcx, dataptr);
-            with_cond(bcx, not_null, |bcx| {
-                let llty = type_of::type_of(ccx, unit_ty);
-                let llsize = machine::llsize_of(ccx, llty);
-                let llalign = C_uint(ccx, machine::llalign_of_min(ccx, llty) as uint);
-                let size = Mul(bcx, llsize, get_len(bcx, vptr));
-                glue::trans_exchange_free_dyn(bcx, dataptr, size, llalign)
-            })
+            let llty = type_of::type_of(ccx, unit_ty);
+            let unit_size = llsize_of_alloc(ccx, llty);
+            if unit_size != 0 {
+                let len = get_len(bcx, vptr);
+                let not_empty = ICmp(bcx, llvm::IntNE, len, C_uint(ccx, 0));
+                with_cond(bcx, not_empty, |bcx| {
+                    let llalign = C_uint(ccx, machine::llalign_of_min(ccx, llty) as uint);
+                    let size = Mul(bcx, C_uint(ccx, unit_size as uint), len);
+                    glue::trans_exchange_free_dyn(bcx, dataptr, size, llalign)
+                })
+            } else {
+                bcx
+            }
         } else {
             bcx
         }
diff --git a/src/test/run-pass/empty-allocation-non-null.rs b/src/test/run-pass/empty-allocation-non-null.rs
index 15544468ae9..56eb340ef59 100644
--- a/src/test/run-pass/empty-allocation-non-null.rs
+++ b/src/test/run-pass/empty-allocation-non-null.rs
@@ -11,6 +11,12 @@
 pub fn main() {
     assert!(Some(box() ()).is_some());
 
+    let xs: Box<[()]> = box [];
+    assert!(Some(xs).is_some());
+
     struct Foo;
     assert!(Some(box Foo).is_some());
+
+    let ys: Box<[Foo]> = box [];
+    assert!(Some(ys).is_some());
 }