Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 19 additions & 5 deletions stdlib/public/core/Collection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1325,17 +1325,31 @@ extension Collection {
return []
}

var result = ContiguousArray<T>()
result.reserveCapacity(n)
let result: ContiguousArray<T>
var p: UnsafeMutablePointer<T>
(result, p) = ContiguousArray<T>._allocateUninitialized(n)

var i = self.startIndex
var initializedElements = 0

for _ in 0..<n {
result.append(try transform(self[i]))
formIndex(after: &i)
do {
for _ in 0..<n {
(p + initializedElements).initialize(to: try transform(self[i]))

formIndex(after: &i)
initializedElements += 1
}
} catch {
// The buffer may not have been initialized entirely. Set its count to
// number of actually initialized items to avoid accessing uninitialized
// memory
result._buffer.count = initializedElements
throw error
}

_expectEnd(of: self, is: i)
_debugPrecondition(initializedElements == n,
"buffer not completely initialized")
return Array(result)
}

Expand Down
26 changes: 21 additions & 5 deletions stdlib/public/core/Sequence.swift
Original file line number Diff line number Diff line change
Expand Up @@ -822,15 +822,31 @@ extension Sequence {
_ transform: (Element) throws -> T
) rethrows -> [T] {
let initialCapacity = underestimatedCount
var result = ContiguousArray<T>()
result.reserveCapacity(initialCapacity)
var result: ContiguousArray<T>
var p: UnsafeMutablePointer<T>
(result, p) = ContiguousArray<T>._allocateUninitialized(initialCapacity)

var iterator = self.makeIterator()

// Add elements up to the initial capacity without checking for regrowth.
for _ in 0..<initialCapacity {
result.append(try transform(iterator.next()!))
var initializedElements = 0

// Initialize the initial capacity of the array without needing to regrow it
do {
for _ in 0..<initialCapacity {
(p + initializedElements).initialize(to: try transform(iterator.next()!))
initializedElements += 1
}
} catch {
// The buffer may not have been initialized entirely. Set its count to
// number of actually initialized items to avoid accessing uninitialized
// memory
result._buffer.count = initializedElements
throw error
}

_debugPrecondition(initializedElements == initialCapacity,
"buffer not completely initialized")

// Add remaining elements, if any.
while let element = iterator.next() {
result.append(try transform(element))
Expand Down
2 changes: 1 addition & 1 deletion test/stdlib/ErrorHandling.swift
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ ErrorHandlingTests.test("ErrorHandling/operators") {

ErrorHandlingTests.test("ErrorHandling/Sequence map") {
let initialCount = NoisyCount
let sequence = AnySequence([1, 2, 3])
let sequence = stride(from: 1, through: 3, by: 1)
for throwAtCount in 0...3 {
var loopCount = 0
do {
Expand Down