@@ -149,46 +149,33 @@ 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
153
- let eraseCount = subrange. count
154
-
155
- 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
152
161
153
let elements = self . firstElementAddress
162
154
163
155
// erase all the elements we're replacing to create a hole
164
156
let holeStart = elements + subrange. lowerBound
165
- let holeEnd = holeStart + newCount
166
-
167
- // directly forwards to Builtin.destroyArray
168
- // TODO: should we branch here or does the compiler branch implicitly?
157
+ let eraseCount = subrange. count
169
158
holeStart. deinitialize ( count: eraseCount)
170
159
171
- // resize the hole to make it the correct size
172
- // safe to always call, moveInitialize to the same location is a no-op
173
- let tailStart = elements + subrange. upperBound
174
- let tailCount = oldCount - subrange. upperBound
175
- holeEnd. moveInitialize ( from: tailStart, count: tailCount)
160
+ let growth = newCount - eraseCount
176
161
177
- // place the values into the hole we created
178
- if newCount > 0 {
179
- let done : Void ? = newValues. withContiguousStorageIfAvailable {
180
- holeStart. initialize ( from: $0. baseAddress!, count: newCount)
181
- }
182
- if done == nil {
183
- var place = holeStart
184
- var i = newValues. startIndex
185
- while place < holeEnd {
186
- place. initialize ( to: newValues [ i] )
187
- place += 1
188
- newValues. formIndex ( after: & i)
189
- }
190
- _expectEnd ( of: newValues, is: i)
191
- }
162
+ // This check will prevent storing a 0 count to the empty array singleton.
163
+ if growth != 0 {
164
+ let holeEnd = holeStart + newCount
165
+ let tailStart = elements + subrange. upperBound
166
+ let tailCount = self . count - subrange. upperBound
167
+ holeEnd. moveInitialize ( from: tailStart, count: tailCount)
168
+ self . count += growth
192
169
}
170
+
171
+ // place the values into the hole we created
172
+ let buf = UnsafeMutableBufferPointer ( start: holeStart, count: newCount)
173
+ let res = buf. initialize ( fromContentsOf: newValues)
174
+ // memory safety: if we did not fill the buffer, we now have
175
+ // uninitialized memory in the middle of our array
176
+ precondition (
177
+ res == buf. endIndex,
178
+ " invalid Collection: count differed in successive traversals "
179
+ )
193
180
}
194
181
}
0 commit comments