@@ -149,75 +149,44 @@ extension _ArrayBufferProtocol {
149
149
elementsOf newValues: __owned C
150
150
) where C: Collection , C. Element == Element {
151
151
_internalInvariant ( startIndex == 0 , " _SliceBuffer should override this function. " )
152
- let oldCount = self . count
152
+ let elements = self . firstElementAddress
153
+
154
+ // erase all the elements we're replacing to create a hole
155
+ let holeStart = elements + subrange. lowerBound
156
+ let holeEnd = holeStart + newCount
153
157
let eraseCount = subrange. count
158
+ holeStart. deinitialize ( count: eraseCount)
154
159
155
160
let growth = newCount - eraseCount
156
- // This check will prevent storing a 0 count to the empty array singleton.
157
- if growth != 0 {
158
- self . count = oldCount + growth
159
- }
160
161
161
- let elements = self . subscriptBaseAddress
162
- let oldTailIndex = subrange. upperBound
163
- let oldTailStart = elements + oldTailIndex
164
- let newTailIndex = oldTailIndex + growth
165
- let newTailStart = oldTailStart + growth
166
- let tailCount = oldCount - subrange. upperBound
167
-
168
- if growth > 0 {
169
- // Slide the tail part of the buffer forwards, in reverse order
170
- // so as not to self-clobber.
171
- newTailStart. moveInitialize ( from: oldTailStart, count: tailCount)
172
-
173
- // Update the original subrange
174
- var i = newValues. startIndex
175
- for j in subrange {
176
- elements [ j] = newValues [ i]
177
- newValues. formIndex ( after: & i)
178
- }
179
- // Initialize the hole left by sliding the tail forward
180
- for j in oldTailIndex..< newTailIndex {
181
- ( elements + j) . initialize ( to: newValues [ i] )
182
- newValues. formIndex ( after: & i)
183
- }
184
- _expectEnd ( of: newValues, is: i)
162
+ if growth != 0 {
163
+ let tailStart = elements + subrange. upperBound
164
+ let tailCount = self . count - subrange. upperBound
165
+ holeEnd. moveInitialize ( from: tailStart, count: tailCount)
166
+ self . count += growth
185
167
}
186
- else { // We're not growing the buffer
187
- // Assign all the new elements into the start of the subrange
188
- var i = subrange. lowerBound
189
- var j = newValues. startIndex
190
- for _ in 0 ..< newCount {
191
- elements [ i] = newValues [ j]
192
- i += 1
193
- newValues. formIndex ( after: & j)
194
- }
195
- _expectEnd ( of: newValues, is: j)
196
-
197
- // If the size didn't change, we're done.
198
- if growth == 0 {
199
- return
200
- }
201
168
202
- // Move the tail backward to cover the shrinkage.
203
- let shrinkage = - growth
204
- if tailCount > shrinkage { // If the tail length exceeds the shrinkage
205
-
206
- // Update the rest of the replaced range with the first
207
- // part of the tail.
208
- newTailStart . moveUpdate ( from : oldTailStart , count : shrinkage )
209
-
210
- // Slide the rest of the tail back
211
- oldTailStart . moveInitialize (
212
- from: oldTailStart + shrinkage , count: tailCount - shrinkage )
169
+ // don't use UnsafeMutableBufferPointer.initialize(fromContentsOf:)
170
+ // since it behaves differently on collections that misreport count,
171
+ // and breaks validation tests for those usecases / potentially
172
+ // breaks ABI guarantees.
173
+ if newCount > 0 {
174
+ let done : Void ? = newValues . withContiguousStorageIfAvailable {
175
+ _precondition (
176
+ $0 . count == newCount ,
177
+ " invalid Collection: count differed in successive traversals "
178
+ )
179
+ holeStart . initialize ( from: $0 . baseAddress! , count: newCount )
213
180
}
214
- else { // Tail fits within erased elements
215
- // Update the start of the replaced range with the tail
216
- newTailStart. moveUpdate ( from: oldTailStart, count: tailCount)
217
-
218
- // Destroy elements remaining after the tail in subrange
219
- ( newTailStart + tailCount) . deinitialize (
220
- count: shrinkage - tailCount)
181
+ if done == nil {
182
+ var place = holeStart
183
+ var i = newValues. startIndex
184
+ while place < holeEnd {
185
+ place. initialize ( to: newValues [ i] )
186
+ place += 1
187
+ newValues. formIndex ( after: & i)
188
+ }
189
+ _expectEnd ( of: newValues, is: i)
221
190
}
222
191
}
223
192
}
0 commit comments