From 063d9ca9283efcf1043c7c706c761f20f6f8d9d3 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 26 Aug 2013 18:17:37 -0700 Subject: [PATCH] std: Make vec::from_elem failure-safe --- src/libstd/vec.rs | 34 ++++++++++++++++++++++++++++++---- 1 file 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(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 } } @@ -3134,6 +3137,29 @@ fn test_from_fn_fail() { }; } + #[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() {