In Xcode 16, Swift introduced stricter concurrency checks. Specifically, mutable captures of inout parameters, like the buffer in your code, are not allowed in concurrently executing code to prevent potential data races.
The key issue is that the buffer parameter, which is an inout parameter to the closure, is being mutated inside a concurrent loop. Swift's new concurrency model is more strict about this to ensure thread safety.
Steps to reproduce
PhoneNumberKit > PhoneNumberKitCore > ParseManager lines 112 and 114
var multiParseArray = [PhoneNumber](unsafeUninitializedCapacity: numberStrings.count) { buffer, initializedCount in
DispatchQueue.concurrentPerform(iterations: numberStrings.count) { [buffer] index in
let numberString = numberStrings[index]
do {
let phoneNumber = try self.parse(numberString, withRegion: region, ignoreType: ignoreType)
**buffer.baseAddress!.advanced(by: index).initialize(to: phoneNumber)**
} catch {
**buffer.baseAddress!.advanced(by: index).initialize(to: PhoneNumber.notPhoneNumber())**
hasError = true
}
}
initializedCount = numberStrings.count
}
Quick Fix
Replace lines 107 - 119 with
// Create a temporary array to hold the parsed phone numbers.
var tempArray = Array<PhoneNumber?>(repeating: nil, count: numberStrings.count)
DispatchQueue.concurrentPerform(iterations: numberStrings.count) { index in
let numberString = numberStrings[index]
do {
let phoneNumber = try self.parse(numberString, withRegion: region, ignoreType: ignoreType)
tempArray[index] = phoneNumber
} catch {
tempArray[index] = PhoneNumber.notPhoneNumber()
hasError = true
}
}
// After the concurrent operation, populate the buffer.
var multiParseArray = [PhoneNumber](unsafeUninitializedCapacity: numberStrings.count) { buffer, initializedCount in
for (index, phoneNumber) in tempArray.enumerated() {
buffer.baseAddress!.advanced(by: index).initialize(to: phoneNumber!)
}
initializedCount = numberStrings.count
}
Environment
iOS Application. Installed with Swift Package Manager
In Xcode 16, Swift introduced stricter concurrency checks. Specifically, mutable captures of inout parameters, like the buffer in your code, are not allowed in concurrently executing code to prevent potential data races.
The key issue is that the buffer parameter, which is an inout parameter to the closure, is being mutated inside a concurrent loop. Swift's new concurrency model is more strict about this to ensure thread safety.
Steps to reproduce
PhoneNumberKit > PhoneNumberKitCore > ParseManager lines 112 and 114
Quick Fix
Replace lines 107 - 119 with
Environment
iOS Application. Installed with Swift Package Manager