@@ -90,8 +90,8 @@ impl<S: Borrow<str>> Join<&str> for [S] {
9090    } 
9191} 
9292
93- macro_rules!  spezialize_for_lengths  { 
94-     ( $separator: expr,  $target: expr,  $iter: expr;  $( $num: expr) ,* )  => { 
93+ macro_rules!  specialize_for_lengths  { 
94+     ( $separator: expr,  $target: expr,  $iter: expr;  $( $num: expr) ,* )  => { { 
9595        let  mut  target = $target; 
9696        let  iter = $iter; 
9797        let  sep_bytes = $separator; 
@@ -102,19 +102,22 @@ macro_rules! spezialize_for_lengths {
102102                $num => { 
103103                    for  s in iter { 
104104                        copy_slice_and_advance!( target,  sep_bytes) ; 
105-                         copy_slice_and_advance!( target,  s. borrow( ) . as_ref( ) ) ; 
105+                         let  content_bytes = s. borrow( ) . as_ref( ) ; 
106+                         copy_slice_and_advance!( target,  content_bytes) ; 
106107                    } 
107108                } , 
108109            ) * 
109110            _ => { 
110111                // arbitrary non-zero size fallback 
111112                for  s in iter { 
112113                    copy_slice_and_advance!( target,  sep_bytes) ; 
113-                     copy_slice_and_advance!( target,  s. borrow( ) . as_ref( ) ) ; 
114+                     let  content_bytes = s. borrow( ) . as_ref( ) ; 
115+                     copy_slice_and_advance!( target,  content_bytes) ; 
114116                } 
115117            } 
116118        } 
117-     } ; 
119+         target
120+     } } 
118121} 
119122
120123macro_rules!  copy_slice_and_advance { 
@@ -153,30 +156,33 @@ where
153156    // if the `len` calculation overflows, we'll panic 
154157    // we would have run out of memory anyway and the rest of the function requires 
155158    // the entire Vec pre-allocated for safety 
156-     let  len  = sep_len
159+     let  reserved_len  = sep_len
157160        . checked_mul ( iter. len ( ) ) 
158161        . and_then ( |n| { 
159162            slice. iter ( ) . map ( |s| s. borrow ( ) . as_ref ( ) . len ( ) ) . try_fold ( n,  usize:: checked_add) 
160163        } ) 
161164        . expect ( "attempt to join into collection with len > usize::MAX" ) ; 
162165
163-     // crucial for safety  
164-     let  mut  result = Vec :: with_capacity ( len ) ; 
165-     assert ! ( result. capacity( )  >= len ) ; 
166+     // prepare an uninitialized buffer  
167+     let  mut  result = Vec :: with_capacity ( reserved_len ) ; 
168+     debug_assert ! ( result. capacity( )  >= reserved_len ) ; 
166169
167170    result. extend_from_slice ( first. borrow ( ) . as_ref ( ) ) ; 
168171
169172    unsafe  { 
170-         { 
171-             let  pos = result. len ( ) ; 
172-             let  target = result. get_unchecked_mut ( pos..len) ; 
173- 
174-             // copy separator and slices over without bounds checks 
175-             // generate loops with hardcoded offsets for small separators 
176-             // massive improvements possible (~ x2) 
177-             spezialize_for_lengths ! ( sep,  target,  iter;  0 ,  1 ,  2 ,  3 ,  4 ) ; 
178-         } 
179-         result. set_len ( len) ; 
173+         let  pos = result. len ( ) ; 
174+         let  target = result. get_unchecked_mut ( pos..reserved_len) ; 
175+ 
176+         // copy separator and slices over without bounds checks 
177+         // generate loops with hardcoded offsets for small separators 
178+         // massive improvements possible (~ x2) 
179+         let  remain = specialize_for_lengths ! ( sep,  target,  iter;  0 ,  1 ,  2 ,  3 ,  4 ) ; 
180+ 
181+         // A weird borrow implementation may return different 
182+         // slices for the length calculation and the actual copy. 
183+         // Make sure we don't expose uninitialized bytes to the caller. 
184+         let  result_len = reserved_len - remain. len ( ) ; 
185+         result. set_len ( result_len) ; 
180186    } 
181187    result
182188} 
0 commit comments