diff options
| author | James Miller <james@aatch.net> | 2014-04-16 14:29:36 +1200 |
|---|---|---|
| committer | James Miller <james@aatch.net> | 2014-04-16 14:29:36 +1200 |
| commit | be334d582435a05ea56c1ca7fcb2e512cfc51f24 (patch) | |
| tree | 900da71bc36964d4cbe260b94db3d1163b74f48a /src/libstd/slice.rs | |
| parent | 42b39924d87739f2dcda3e788c6e8655d310954f (diff) | |
| download | rust-be334d582435a05ea56c1ca7fcb2e512cfc51f24.tar.gz rust-be334d582435a05ea56c1ca7fcb2e512cfc51f24.zip | |
Make Vec::clone and slice::to_owned failure-safe
Diffstat (limited to 'src/libstd/slice.rs')
| -rw-r--r-- | src/libstd/slice.rs | 25 |
1 files changed, 15 insertions, 10 deletions
diff --git a/src/libstd/slice.rs b/src/libstd/slice.rs index f4f97ea8c92..153e21c780c 100644 --- a/src/libstd/slice.rs +++ b/src/libstd/slice.rs @@ -762,18 +762,23 @@ impl<'a, T: Clone> CloneableVector<T> for &'a [T] { fn to_owned(&self) -> ~[T] { let len = self.len(); let mut result = with_capacity(len); + // Unsafe code so this can be optimised to a memcpy (or something + // similarly fast) when T is Copy. LLVM is easily confused, so any + // extra operations during the loop can prevent this optimisation unsafe { - // Unsafe code so this can be optimised to a memcpy (or something - // similarly fast) when T is Copy. LLVM is easily confused, so any - // extra operations during the loop can prevent this optimisation - result.set_len(len); let mut i = 0; - while i < len { - mem::move_val_init( - result.unsafe_mut_ref(i), - self.unsafe_ref(i).clone()); - i = i + 1; - } + let p = result.as_mut_ptr(); + // Use try_finally here otherwise the write to length + // inside the loop stops LLVM from optimising this. + try_finally( + &mut i, (), + |i, ()| while *i < len { + mem::move_val_init( + &mut(*p.offset(*i as int)), + self.unsafe_ref(*i).clone()); + *i += 1; + }, + |i| result.set_len(*i)); } result } |
