@@ -824,8 +824,26 @@ impl<T> ThinVec<T> {
824824 if old_len == self . capacity ( ) {
825825 self . reserve ( 1 ) ;
826826 }
827+ unsafe {
828+ // SAFETY: reserve() ensures sufficient capacity.
829+ self . push_reserved ( val) ;
830+ }
831+ }
832+
833+ /// Appends an element to the back like `push`,
834+ /// but assumes that sufficient capacity has already been reserved, i.e.
835+ /// `len() < capacity()`.
836+ ///
837+ /// # Safety
838+ ///
839+ /// - Capacity must be reserved in advance such that `capacity() > len()`.
840+ pub unsafe fn push_reserved ( & mut self , val : T ) {
841+ let old_len = self . len ( ) ;
842+
827843 unsafe {
828844 ptr:: write ( self . data_raw ( ) . add ( old_len) , val) ;
845+
846+ // SAFETY: capacity > len >= 0, so capacity != 0, so this is not a singleton.
829847 self . set_len_non_singleton ( old_len + 1 ) ;
830848 }
831849 }
@@ -1927,11 +1945,19 @@ impl<T> Extend<T> for ThinVec<T> {
19271945 where
19281946 I : IntoIterator < Item = T > ,
19291947 {
1930- let iter = iter. into_iter ( ) ;
1948+ let mut iter = iter. into_iter ( ) ;
19311949 let hint = iter. size_hint ( ) . 0 ;
19321950 if hint > 0 {
19331951 self . reserve ( hint) ;
19341952 }
1953+ for x in iter. by_ref ( ) . take ( hint) {
1954+ // SAFETY: `reserve(hint)` ensures the next `hint` calls of `push_reserved`
1955+ // have sufficient capacity.
1956+ unsafe { self . push_reserved ( x) ; }
1957+ }
1958+
1959+ // if the hint underestimated the iterator length,
1960+ // push the remaining items with capacity check each time.
19351961 for x in iter {
19361962 self . push ( x) ;
19371963 }
0 commit comments