@@ -54,7 +54,7 @@ use core::ops::AddAssign;
5454use core:: ops:: Bound :: { Excluded , Included , Unbounded } ;
5555use core:: ops:: { self , Range , RangeBounds } ;
5656use core:: str:: pattern:: { Pattern , Utf8Pattern } ;
57- use core:: { fmt, hash, ptr, slice} ;
57+ use core:: { array , fmt, hash, ptr, slice} ;
5858
5959#[ cfg( not( no_global_oom_handling) ) ]
6060use crate :: alloc:: Allocator ;
@@ -2203,6 +2203,35 @@ impl String {
22032203 let slice = self . vec . leak ( ) ;
22042204 unsafe { from_utf8_unchecked_mut ( slice) }
22052205 }
2206+
2207+ /// SAFETY: `impl AsRef<str> for S` must be stable
2208+ #[ cfg( not( no_global_oom_handling) ) ]
2209+ unsafe fn extend_many < S : AsRef < str > > ( & mut self , vals : & [ S ] ) {
2210+ let additional = vals. iter ( ) . fold ( 0usize , |a, s| a. saturating_add ( s. as_ref ( ) . len ( ) ) ) ;
2211+ self . reserve ( additional) ;
2212+
2213+ let mut spare = self . vec . spare_capacity_mut ( ) . as_mut_ptr ( ) . cast_init ( ) ;
2214+ for val in vals {
2215+ let val = val. as_ref ( ) ;
2216+ // SAFETY:
2217+ // - `val` is a valid &str, so `val.as_ptr()` is valid
2218+ // for `val.len()` bytes and properly initialized.
2219+ // - `spare` points to valid spare capacity in the Vec
2220+ // with enough space for `val.len()` bytes.
2221+ // This is guaranteed because the caller ensures
2222+ // that `.as_ref()` is stable, and the saturating
2223+ // addition stops undercounting by overflow.
2224+ // - Both pointers are byte-aligned and the regions cannot overlap.
2225+ unsafe {
2226+ ptr:: copy_nonoverlapping ( val. as_ptr ( ) , spare, val. len ( ) ) ;
2227+ spare = spare. add ( val. len ( ) ) ;
2228+ }
2229+ }
2230+
2231+ let new_len = self . vec . len ( ) + additional;
2232+ // SAFETY: the elements have just been initialized
2233+ unsafe { self . vec . set_len ( new_len) }
2234+ }
22062235}
22072236
22082237impl FromUtf8Error {
@@ -2502,7 +2531,8 @@ impl<'a> Extend<&'a char> for String {
25022531#[ stable( feature = "rust1" , since = "1.0.0" ) ]
25032532impl < ' a > Extend < & ' a str > for String {
25042533 fn extend < I : IntoIterator < Item = & ' a str > > ( & mut self , iter : I ) {
2505- iter. into_iter ( ) . for_each ( move |s| self . push_str ( s) ) ;
2534+ // SAFETY: `impl AsRef<str> for &str` is stable
2535+ unsafe { self . extend_many_chunked ( iter. into_iter ( ) ) }
25062536 }
25072537
25082538 #[ inline]
@@ -2515,15 +2545,17 @@ impl<'a> Extend<&'a str> for String {
25152545#[ stable( feature = "box_str2" , since = "1.45.0" ) ]
25162546impl < A : Allocator > Extend < Box < str , A > > for String {
25172547 fn extend < I : IntoIterator < Item = Box < str , A > > > ( & mut self , iter : I ) {
2518- iter. into_iter ( ) . for_each ( move |s| self . push_str ( & s) ) ;
2548+ // SAFETY: `impl AsRef<str> for Box<str, A>` is stable
2549+ unsafe { self . extend_many_chunked ( iter. into_iter ( ) ) }
25192550 }
25202551}
25212552
25222553#[ cfg( not( no_global_oom_handling) ) ]
25232554#[ stable( feature = "extend_string" , since = "1.4.0" ) ]
25242555impl Extend < String > for String {
25252556 fn extend < I : IntoIterator < Item = String > > ( & mut self , iter : I ) {
2526- iter. into_iter ( ) . for_each ( move |s| self . push_str ( & s) ) ;
2557+ // SAFETY: `impl AsRef<str> for String` is stable
2558+ unsafe { self . extend_many_chunked ( iter. into_iter ( ) ) }
25272559 }
25282560
25292561 #[ inline]
@@ -2536,7 +2568,8 @@ impl Extend<String> for String {
25362568#[ stable( feature = "herd_cows" , since = "1.19.0" ) ]
25372569impl < ' a > Extend < Cow < ' a , str > > for String {
25382570 fn extend < I : IntoIterator < Item = Cow < ' a , str > > > ( & mut self , iter : I ) {
2539- iter. into_iter ( ) . for_each ( move |s| self . push_str ( & s) ) ;
2571+ // SAFETY: `impl AsRef<str> for Cow<'a, str>` is stable
2572+ unsafe { self . extend_many_chunked ( iter. into_iter ( ) ) }
25402573 }
25412574
25422575 #[ inline]
@@ -2573,6 +2606,71 @@ impl<'a> Extend<&'a core::ascii::Char> for String {
25732606 }
25742607}
25752608
2609+ #[ cfg( not( no_global_oom_handling) ) ]
2610+ trait ExtendManySpec < S , I > {
2611+ /// SAFETY: `impl AsRef<str> for S` must be stable
2612+ unsafe fn extend_many_chunked ( & mut self , iter : I ) ;
2613+ }
2614+
2615+ #[ cfg( not( no_global_oom_handling) ) ]
2616+ impl < S , I > ExtendManySpec < S , I > for String
2617+ where
2618+ S : AsRef < str > ,
2619+ I : Iterator < Item = S > ,
2620+ {
2621+ default unsafe fn extend_many_chunked ( & mut self , mut iter : I ) {
2622+ let mut repeat = true ;
2623+ while repeat {
2624+ let chunk = match iter. next_chunk :: < 8 > ( ) {
2625+ Ok ( chunk) => chunk. into_iter ( ) ,
2626+ Err ( partial_chunk) => {
2627+ repeat = false ;
2628+ partial_chunk
2629+ }
2630+ } ;
2631+
2632+ // SAFETY: the caller ensures that `impl AsRef<str> for S` is stable
2633+ unsafe { self . extend_many ( chunk. as_slice ( ) ) }
2634+ }
2635+ }
2636+ }
2637+
2638+ // TODO: specialization thinks that this is a conflicting implementation
2639+ /*
2640+ #[cfg(not(no_global_oom_handling))]
2641+ impl<'a, S> ExtendManySpec<S, slice::Iter<'a, S>> for String
2642+ where
2643+ S: AsRef<str>,
2644+ {
2645+ unsafe fn extend_many_chunked(&mut self, iter: slice::Iter<'a, S>) {
2646+ // SAFETY: the caller ensures that `impl AsRef<str> for S` is stable
2647+ unsafe { self.extend_many(iter.as_slice()) }
2648+ }
2649+ }
2650+ */
2651+
2652+ #[ cfg( not( no_global_oom_handling) ) ]
2653+ impl < S , const N : usize > ExtendManySpec < S , array:: IntoIter < S , N > > for String
2654+ where
2655+ S : AsRef < str > ,
2656+ {
2657+ unsafe fn extend_many_chunked ( & mut self , iter : array:: IntoIter < S , N > ) {
2658+ // SAFETY: the caller ensures that `impl AsRef<str> for S` is stable
2659+ unsafe { self . extend_many ( iter. as_slice ( ) ) }
2660+ }
2661+ }
2662+
2663+ #[ cfg( not( no_global_oom_handling) ) ]
2664+ impl < S > ExtendManySpec < S , vec:: IntoIter < S > > for String
2665+ where
2666+ S : AsRef < str > ,
2667+ {
2668+ unsafe fn extend_many_chunked ( & mut self , iter : vec:: IntoIter < S > ) {
2669+ // SAFETY: the caller ensures that `impl AsRef<str> for S` is stable
2670+ unsafe { self . extend_many ( iter. as_slice ( ) ) }
2671+ }
2672+ }
2673+
25762674/// A convenience impl that delegates to the impl for `&str`.
25772675///
25782676/// # Examples
0 commit comments