about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2013-08-26 18:17:37 -0700
committerBrian Anderson <banderson@mozilla.com>2013-08-26 18:17:56 -0700
commit063d9ca9283efcf1043c7c706c761f20f6f8d9d3 (patch)
tree2e8a8dc3952e0949f444803eed0ea7d739ae22b7
parenta8221bd5e2cf05cea7546ebdd5331d17a3e4a4c5 (diff)
downloadrust-063d9ca9283efcf1043c7c706c761f20f6f8d9d3.tar.gz
rust-063d9ca9283efcf1043c7c706c761f20f6f8d9d3.zip
std: Make vec::from_elem failure-safe
-rw-r--r--src/libstd/vec.rs34
1 files changed, 30 insertions, 4 deletions
diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs
index 976a3cafb32..3e9c4b788fe 100644
--- a/src/libstd/vec.rs
+++ b/src/libstd/vec.rs
@@ -125,11 +125,14 @@ pub fn from_elem<T:Clone>(n_elts: uint, t: T) -> ~[T] {
         let mut v = with_capacity(n_elts);
         let p = raw::to_mut_ptr(v);
         let mut i = 0u;
-        while i < n_elts {
-            intrinsics::move_val_init(&mut(*ptr::mut_offset(p, i as int)), t.clone());
-            i += 1u;
+        do (|| {
+            while i < n_elts {
+                intrinsics::move_val_init(&mut(*ptr::mut_offset(p, i as int)), t.clone());
+                i += 1u;
+            }
+        }).finally {
+            raw::set_len(&mut v, i);
         }
-        raw::set_len(&mut v, n_elts);
         v
     }
 }
@@ -3136,6 +3139,29 @@ mod tests {
 
     #[test]
     #[should_fail]
+    fn test_from_elem_fail() {
+        use cast;
+
+        struct S {
+            f: int,
+            boxes: (~int, @int)
+        }
+
+        impl Clone for S {
+            fn clone(&self) -> S {
+                let s = unsafe { cast::transmute_mut(self) };
+                s.f += 1;
+                if s.f == 10 { fail!() }
+                S { f: s.f, boxes: s.boxes.clone() }
+            }
+        }
+
+        let s = S { f: 0, boxes: (~0, @0) };
+        let _ = from_elem(100, s);
+    }
+
+    #[test]
+    #[should_fail]
     fn test_build_fail() {
         do build |push| {
             push((~0, @0));