diff options
| author | Brian Anderson <banderson@mozilla.com> | 2013-08-26 18:17:37 -0700 |
|---|---|---|
| committer | Brian Anderson <banderson@mozilla.com> | 2013-08-26 18:17:56 -0700 |
| commit | 063d9ca9283efcf1043c7c706c761f20f6f8d9d3 (patch) | |
| tree | 2e8a8dc3952e0949f444803eed0ea7d739ae22b7 | |
| parent | a8221bd5e2cf05cea7546ebdd5331d17a3e4a4c5 (diff) | |
| download | rust-063d9ca9283efcf1043c7c706c761f20f6f8d9d3.tar.gz rust-063d9ca9283efcf1043c7c706c761f20f6f8d9d3.zip | |
std: Make vec::from_elem failure-safe
| -rw-r--r-- | src/libstd/vec.rs | 34 |
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)); |
