@@ -2927,15 +2927,7 @@ impl<T> [T] {
2927
2927
where
2928
2928
T : Clone ,
2929
2929
{
2930
- assert ! ( self . len( ) == src. len( ) , "destination and source slices have different lengths" ) ;
2931
- // NOTE: We need to explicitly slice them to the same length
2932
- // for bounds checking to be elided, and the optimizer will
2933
- // generate memcpy for simple cases (for example T = u8).
2934
- let len = self . len ( ) ;
2935
- let src = & src[ ..len] ;
2936
- for i in 0 ..len {
2937
- self [ i] . clone_from ( & src[ i] ) ;
2938
- }
2930
+ self . spec_clone_from ( src) ;
2939
2931
}
2940
2932
2941
2933
/// Copies all elements from `src` into `self`, using a memcpy.
@@ -3440,6 +3432,36 @@ impl<T> [T] {
3440
3432
}
3441
3433
}
3442
3434
3435
+ trait CloneFromSpec < T > {
3436
+ fn spec_clone_from ( & mut self , src : & [ T ] ) ;
3437
+ }
3438
+
3439
+ impl < T > CloneFromSpec < T > for [ T ]
3440
+ where
3441
+ T : Clone ,
3442
+ {
3443
+ default fn spec_clone_from ( & mut self , src : & [ T ] ) {
3444
+ assert ! ( self . len( ) == src. len( ) , "destination and source slices have different lengths" ) ;
3445
+ // NOTE: We need to explicitly slice them to the same length
3446
+ // to make it easier for the optimizer to elide bounds checking.
3447
+ // But since it can't be relied on we also have an explicit specialization for T: Copy.
3448
+ let len = self . len ( ) ;
3449
+ let src = & src[ ..len] ;
3450
+ for i in 0 ..len {
3451
+ self [ i] . clone_from ( & src[ i] ) ;
3452
+ }
3453
+ }
3454
+ }
3455
+
3456
+ impl < T > CloneFromSpec < T > for [ T ]
3457
+ where
3458
+ T : Copy ,
3459
+ {
3460
+ fn spec_clone_from ( & mut self , src : & [ T ] ) {
3461
+ self . copy_from_slice ( src) ;
3462
+ }
3463
+ }
3464
+
3443
3465
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
3444
3466
impl < T > Default for & [ T ] {
3445
3467
/// Creates an empty slice.
0 commit comments