about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorJed Davis <jld@panix.com>2013-01-08 00:24:43 -0800
committerTim Chevalier <chevalier@alum.wellesley.edu>2013-01-13 14:37:59 -0800
commit1b01629f189f1c4050bd5c7eac81e44ba2c7a76f (patch)
treea958ba05b82b2948ca24891931c704f69ad9014f /src/libcore
parentea53c48ca23ec4e46454d48936c209d2a67cf892 (diff)
Make vectors (& old ports) of zero-size types allocate one byte each.
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/oldcomm.rs3
-rw-r--r--src/libcore/sys.rs21
-rw-r--r--src/libcore/vec.rs32
3 files changed, 44 insertions, 12 deletions
diff --git a/src/libcore/oldcomm.rs b/src/libcore/oldcomm.rs
index 65aaf1fe428..ae3116b08f0 100644
--- a/src/libcore/oldcomm.rs
+++ b/src/libcore/oldcomm.rs
@@ -91,7 +91,8 @@ pub enum Chan<T: Owned> {
 /// Constructs a port
 pub fn Port<T: Owned>() -> Port<T> {
     unsafe {
-        Port_(@PortPtr(rustrt::new_port(sys::size_of::<T>() as size_t)))
+        Port_(@PortPtr(rustrt::new_port(sys::nonzero_size_of::<T>()
+                                        as size_t)))
     }
 }
 
diff --git a/src/libcore/sys.rs b/src/libcore/sys.rs
index ad9c3d1e51d..322aa895eb4 100644
--- a/src/libcore/sys.rs
+++ b/src/libcore/sys.rs
@@ -88,6 +88,17 @@ pub pure fn size_of<T>() -> uint {
 }
 
 /**
+ * Returns the size of a type, or 1 if the actual size is zero.
+ *
+ * Useful for building structures containing variable-length arrays.
+ */
+#[inline(always)]
+pub pure fn nonzero_size_of<T>() -> uint {
+    let s = size_of::<T>();
+    if s == 0 { 1 } else { s }
+}
+
+/**
  * Returns the ABI-required minimum alignment of a type
  *
  * This is the alignment used for struct fields. It may be smaller
@@ -146,7 +157,7 @@ pub pure fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! {
 #[cfg(test)]
 pub mod tests {
     use cast;
-    use sys::{Closure, pref_align_of, size_of};
+    use sys::{Closure, pref_align_of, size_of, nonzero_size_of};
 
     #[test]
     pub fn size_of_basic() {
@@ -172,6 +183,14 @@ pub mod tests {
     }
 
     #[test]
+    pub fn nonzero_size_of_basic() {
+        type Z = [i8 * 0];
+        assert size_of::<Z>() == 0u;
+        assert nonzero_size_of::<Z>() == 1u;
+        assert nonzero_size_of::<uint>() == size_of::<uint>();
+    }
+
+    #[test]
     pub fn align_of_basic() {
         assert pref_align_of::<u8>() == 1u;
         assert pref_align_of::<u16>() == 2u;
diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs
index b9cefa89aa7..29767f3c1e0 100644
--- a/src/libcore/vec.rs
+++ b/src/libcore/vec.rs
@@ -103,7 +103,7 @@ pub fn reserve_at_least<T>(v: &mut ~[T], n: uint) {
 pub pure fn capacity<T>(v: &const ~[T]) -> uint {
     unsafe {
         let repr: **raw::VecRepr = ::cast::transmute(v);
-        (**repr).unboxed.alloc / sys::size_of::<T>()
+        (**repr).unboxed.alloc / sys::nonzero_size_of::<T>()
     }
 }
 
@@ -276,7 +276,7 @@ pub pure fn view<T>(v: &r/[T], start: uint, end: uint) -> &r/[T] {
         unsafe {
             ::cast::reinterpret_cast(
                 &(ptr::offset(p, start),
-                  (end - start) * sys::size_of::<T>()))
+                  (end - start) * sys::nonzero_size_of::<T>()))
         }
     }
 }
@@ -289,7 +289,7 @@ pub pure fn mut_view<T>(v: &r/[mut T], start: uint, end: uint) -> &r/[mut T] {
         unsafe {
             ::cast::reinterpret_cast(
                 &(ptr::mut_offset(p, start),
-                  (end - start) * sys::size_of::<T>()))
+                  (end - start) * sys::nonzero_size_of::<T>()))
         }
     }
 }
@@ -303,7 +303,7 @@ pub pure fn const_view<T>(v: &r/[const T], start: uint,
         unsafe {
             ::cast::reinterpret_cast(
                 &(ptr::const_offset(p, start),
-                  (end - start) * sys::size_of::<T>()))
+                  (end - start) * sys::nonzero_size_of::<T>()))
         }
     }
 }
@@ -608,7 +608,7 @@ pub fn push<T>(v: &mut ~[T], initval: T) {
 unsafe fn push_fast<T>(v: &mut ~[T], initval: T) {
     let repr: **raw::VecRepr = ::cast::transmute(v);
     let fill = (**repr).unboxed.fill;
-    (**repr).unboxed.fill += sys::size_of::<T>();
+    (**repr).unboxed.fill += sys::nonzero_size_of::<T>();
     let p = addr_of(&((**repr).unboxed.data));
     let p = ptr::offset(p, fill) as *mut T;
     rusti::move_val_init(&mut(*p), move initval);
@@ -1449,7 +1449,7 @@ pub pure fn as_imm_buf<T,U>(s: &[T],
         let v : *(*T,uint) =
             ::cast::reinterpret_cast(&addr_of(&s));
         let (buf,len) = *v;
-        f(buf, len / sys::size_of::<T>())
+        f(buf, len / sys::nonzero_size_of::<T>())
     }
 }
 
@@ -1462,7 +1462,7 @@ pub pure fn as_const_buf<T,U>(s: &[const T],
         let v : *(*const T,uint) =
             ::cast::reinterpret_cast(&addr_of(&s));
         let (buf,len) = *v;
-        f(buf, len / sys::size_of::<T>())
+        f(buf, len / sys::nonzero_size_of::<T>())
     }
 }
 
@@ -1475,7 +1475,7 @@ pub pure fn as_mut_buf<T,U>(s: &[mut T],
         let v : *(*mut T,uint) =
             ::cast::reinterpret_cast(&addr_of(&s));
         let (buf,len) = *v;
-        f(buf, len / sys::size_of::<T>())
+        f(buf, len / sys::nonzero_size_of::<T>())
     }
 }
 
@@ -1992,7 +1992,7 @@ pub mod raw {
     #[inline(always)]
     pub unsafe fn set_len<T>(v: &mut ~[T], new_len: uint) {
         let repr: **VecRepr = ::cast::transmute(v);
-        (**repr).unboxed.fill = new_len * sys::size_of::<T>();
+        (**repr).unboxed.fill = new_len * sys::nonzero_size_of::<T>();
     }
 
     /**
@@ -2032,7 +2032,7 @@ pub mod raw {
     pub unsafe fn buf_as_slice<T,U>(p: *T,
                                     len: uint,
                                     f: fn(v: &[T]) -> U) -> U {
-        let pair = (p, len * sys::size_of::<T>());
+        let pair = (p, len * sys::nonzero_size_of::<T>());
         let v : *(&blk/[T]) =
             ::cast::reinterpret_cast(&addr_of(&pair));
         f(*v)
@@ -2502,6 +2502,18 @@ mod tests {
     }
 
     #[test]
+    fn test_len_divzero() {
+        type Z = [i8 * 0];
+        let v0 : &[Z] = &[];
+        let v1 : &[Z] = &[[]];
+        let v2 : &[Z] = &[[], []];
+        assert(sys::size_of::<Z>() == 0);
+        assert(len(v0) == 0);
+        assert(len(v1) == 1);
+        assert(len(v2) == 2);
+    }
+
+    #[test]
     fn test_head() {
         let a = ~[11, 12];
         assert (head(a) == 11);