Skip to content

Commit 435a333

Browse files
committed
[stdlib] replaceSubrange code cleanup
Add an explanation about why UMBP.initialize(fromContentsOf:) can't be used.
1 parent f2abb35 commit 435a333

File tree

1 file changed

+17
-18
lines changed

1 file changed

+17
-18
lines changed

stdlib/public/core/ArrayBufferProtocol.swift

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -149,34 +149,33 @@ extension _ArrayBufferProtocol {
149149
elementsOf newValues: __owned C
150150
) where C: Collection, C.Element == Element {
151151
_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-
161152
let elements = self.firstElementAddress
162153

163154
// erase all the elements we're replacing to create a hole
164155
let holeStart = elements + subrange.lowerBound
165156
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
169158
holeStart.deinitialize(count: eraseCount)
170159

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
161+
162+
if growth != 0 {
163+
let tailStart = elements + subrange.upperBound
164+
let tailCount = oldCount - subrange.upperBound
165+
holeEnd.moveInitialize(from: tailStart, count: tailCount)
166+
self.count += growth
167+
}
176168

177-
// place the values into the hole we created
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.
178173
if newCount > 0 {
179174
let done: Void? = newValues.withContiguousStorageIfAvailable {
175+
_precondition(
176+
$0.count == newCount,
177+
"invalid Collection: count differed in successive traversals"
178+
)
180179
holeStart.initialize(from: $0.baseAddress!, count: newCount)
181180
}
182181
if done == nil {

0 commit comments

Comments
 (0)