@@ -197,7 +197,9 @@ impl<T: Clone> Vec<T> {
197
197
/// ```
198
198
#[ inline]
199
199
pub fn from_slice ( values : & [ T ] ) -> Vec < T > {
200
- values. iter ( ) . map ( |x| x. clone ( ) ) . collect ( )
200
+ let mut vector = Vec :: with_capacity ( values. len ( ) ) ;
201
+ vector. push_all ( values) ;
202
+ vector
201
203
}
202
204
203
205
/// Constructs a `Vec` with copies of a value.
@@ -238,7 +240,10 @@ impl<T: Clone> Vec<T> {
238
240
/// ```
239
241
#[ inline]
240
242
pub fn push_all ( & mut self , other : & [ T ] ) {
241
- self . extend ( other. iter ( ) . map ( |e| e. clone ( ) ) ) ;
243
+ unsafe {
244
+ self . reserve_additional ( other. len ( ) ) ;
245
+ unsafe_push_all_clone ( self , other)
246
+ }
242
247
}
243
248
244
249
/// Grows the `Vec` in-place.
@@ -318,41 +323,31 @@ impl<T: Clone> Vec<T> {
318
323
#[ unstable]
319
324
impl < T : Clone > Clone for Vec < T > {
320
325
fn clone ( & self ) -> Vec < T > {
321
- let len = self . len ;
322
- let mut vector = Vec :: with_capacity ( len) ;
323
- // Unsafe code so this can be optimised to a memcpy (or something
324
- // similarly fast) when T is Copy. LLVM is easily confused, so any
325
- // extra operations during the loop can prevent this optimisation
326
- {
327
- let this_slice = self . as_slice ( ) ;
328
- while vector. len < len {
329
- unsafe {
330
- let len = vector. len ;
331
- ptr:: write (
332
- vector. as_mut_slice ( ) . unsafe_mut_ref ( len) ,
333
- this_slice. unsafe_ref ( len) . clone ( ) ) ;
334
- }
335
- vector. len += 1 ;
336
- }
326
+ unsafe {
327
+ let mut vector = Vec :: with_capacity ( self . len ) ;
328
+ unsafe_push_all_clone ( & mut vector, self . as_slice ( ) ) ;
329
+ vector
337
330
}
338
- vector
339
331
}
340
332
341
333
fn clone_from ( & mut self , other : & Vec < T > ) {
342
- // drop anything in self that will not be overwritten
343
- if self . len ( ) > other. len ( ) {
344
- self . truncate ( other. len ( ) )
345
- }
334
+ unsafe {
335
+ // drop anything in self that will not be overwritten
336
+ if self . len ( ) > other. len ( ) {
337
+ self . truncate ( other. len ( ) )
338
+ }
346
339
347
- // reuse the contained values' allocations/resources.
348
- for ( place, thing) in self . mut_iter ( ) . zip ( other. iter ( ) ) {
349
- place. clone_from ( thing)
350
- }
340
+ // reuse the contained values' allocations/resources.
341
+ for ( place, thing) in self . mut_iter ( ) . zip ( other. iter ( ) ) {
342
+ place. clone_from ( thing)
343
+ }
351
344
352
- // self.len <= other.len due to the truncate above, so the
353
- // slice here is always in-bounds.
354
- let len = self . len ( ) ;
355
- self . extend ( other. slice_from ( len) . iter ( ) . map ( |x| x. clone ( ) ) ) ;
345
+ // self.len <= other.len due to the truncate above, so the
346
+ // slice here is always in-bounds.
347
+ let slice = other. slice_from ( self . len ( ) ) ;
348
+ self . reserve_additional ( slice. len ( ) ) ;
349
+ unsafe_push_all_clone ( self , slice)
350
+ }
356
351
}
357
352
}
358
353
@@ -1555,6 +1550,24 @@ pub mod raw {
1555
1550
}
1556
1551
}
1557
1552
1553
+ // Unsafe code so this can be optimised to a memcpy (or something similarly
1554
+ // fast) when T is Copy. LLVM is easily confused, so any extra operations
1555
+ // during the loop can prevent this optimisation.
1556
+ //
1557
+ // WARNING: You must preallocate space on the vector before you call this
1558
+ // method.
1559
+ #[ inline( always) ]
1560
+ unsafe fn unsafe_push_all_clone < T : Clone > ( dst : & mut Vec < T > , src : & [ T ] ) {
1561
+ let mut dst_len = dst. len ( ) ;
1562
+
1563
+ for i in range ( 0 , src. len ( ) ) {
1564
+ ptr:: write (
1565
+ dst. as_mut_slice ( ) . unsafe_mut_ref ( dst_len) ,
1566
+ src. unsafe_ref ( i) . clone ( ) ) ;
1567
+ dst_len += 1 ;
1568
+ dst. set_len ( dst_len) ;
1569
+ }
1570
+ }
1558
1571
1559
1572
#[ cfg( test) ]
1560
1573
mod tests {
0 commit comments