@@ -2203,6 +2203,46 @@ impl String {
22032203 let slice = self . vec . leak ( ) ;
22042204 unsafe { from_utf8_unchecked_mut ( slice) }
22052205 }
2206+
2207+ // SAFETY: the `impl AsRef<str> for S` must be stable
2208+ #[ cfg( not( no_global_oom_handling) ) ]
2209+ unsafe fn extend_many_chunked < S : AsRef < str > , I : IntoIterator < Item = S > > ( & mut self , iter : I ) {
2210+ let mut iter = iter. into_iter ( ) ;
2211+
2212+ let mut repeat = true ;
2213+ while repeat {
2214+ let chunk = match iter. next_chunk :: < 8 > ( ) {
2215+ Ok ( chunk) => chunk. into_iter ( ) ,
2216+ Err ( partial_chunk) => {
2217+ repeat = false ;
2218+ partial_chunk
2219+ }
2220+ } ;
2221+
2222+ // SAFETY: the caller must ensure that `impl AsRef<str> for S` is stable
2223+ unsafe { self . extend_many ( chunk. as_slice ( ) ) }
2224+ }
2225+ }
2226+
2227+ // SAFETY: the `AsRef<str>` implementation must be stable
2228+ #[ cfg( not( no_global_oom_handling) ) ]
2229+ unsafe fn extend_many < S : AsRef < str > > ( & mut self , vals : & [ S ] ) {
2230+ let additional = vals. iter ( ) . fold ( 0usize , |a, s| a. saturating_add ( s. as_ref ( ) . len ( ) ) ) ;
2231+ self . reserve ( additional) ;
2232+
2233+ let mut spare = self . vec . spare_capacity_mut ( ) . as_mut_ptr ( ) . cast_init ( ) ;
2234+ for val in vals {
2235+ let val = val. as_ref ( ) ;
2236+ // TODO: document safety
2237+ unsafe { ptr:: copy_nonoverlapping ( val. as_ptr ( ) , spare, val. len ( ) ) }
2238+ // TODO: document safety
2239+ spare = unsafe { spare. add ( val. len ( ) ) } ;
2240+ }
2241+
2242+ let new_len = self . vec . len ( ) + additional;
2243+ // SAFETY: the elements have just been initialized
2244+ unsafe { self . vec . set_len ( new_len) }
2245+ }
22062246}
22072247
22082248impl FromUtf8Error {
@@ -2502,7 +2542,8 @@ impl<'a> Extend<&'a char> for String {
25022542#[ stable( feature = "rust1" , since = "1.0.0" ) ]
25032543impl < ' a > Extend < & ' a str > for String {
25042544 fn extend < I : IntoIterator < Item = & ' a str > > ( & mut self , iter : I ) {
2505- iter. into_iter ( ) . for_each ( move |s| self . push_str ( s) ) ;
2545+ // SAFETY: `impl AsRef<str> for &str` is stable
2546+ unsafe { self . extend_many_chunked ( iter) }
25062547 }
25072548
25082549 #[ inline]
@@ -2515,15 +2556,17 @@ impl<'a> Extend<&'a str> for String {
25152556#[ stable( feature = "box_str2" , since = "1.45.0" ) ]
25162557impl < A : Allocator > Extend < Box < str , A > > for String {
25172558 fn extend < I : IntoIterator < Item = Box < str , A > > > ( & mut self , iter : I ) {
2518- iter. into_iter ( ) . for_each ( move |s| self . push_str ( & s) ) ;
2559+ // SAFETY: `impl AsRef<str> for Box<str, A>` is stable
2560+ unsafe { self . extend_many_chunked ( iter) }
25192561 }
25202562}
25212563
25222564#[ cfg( not( no_global_oom_handling) ) ]
25232565#[ stable( feature = "extend_string" , since = "1.4.0" ) ]
25242566impl Extend < String > for String {
25252567 fn extend < I : IntoIterator < Item = String > > ( & mut self , iter : I ) {
2526- iter. into_iter ( ) . for_each ( move |s| self . push_str ( & s) ) ;
2568+ // SAFETY: `impl AsRef<str> for String` is stable
2569+ unsafe { self . extend_many_chunked ( iter) }
25272570 }
25282571
25292572 #[ inline]
@@ -2536,7 +2579,8 @@ impl Extend<String> for String {
25362579#[ stable( feature = "herd_cows" , since = "1.19.0" ) ]
25372580impl < ' a > Extend < Cow < ' a , str > > for String {
25382581 fn extend < I : IntoIterator < Item = Cow < ' a , str > > > ( & mut self , iter : I ) {
2539- iter. into_iter ( ) . for_each ( move |s| self . push_str ( & s) ) ;
2582+ // SAFETY: `impl AsRef<str> for Cow<'a, str>` is stable
2583+ unsafe { self . extend_many_chunked ( iter) }
25402584 }
25412585
25422586 #[ inline]
0 commit comments