Skip to content

Commit 4d037ce

Browse files
committed
Adopt typed throws for withUnsafeMutableBufferPointer
1 parent 5c07fd9 commit 4d037ce

File tree

9 files changed

+139
-59
lines changed

9 files changed

+139
-59
lines changed

stdlib/public/core/Array.swift

Lines changed: 35 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1612,50 +1612,17 @@ extension Array {
16121612
return try _buffer.withUnsafeBufferPointer(body)
16131613
}
16141614

1615-
/// Calls the given closure with a pointer to the array's mutable contiguous
1616-
/// storage.
1617-
///
1618-
/// Often, the optimizer can eliminate bounds checks within an array
1619-
/// algorithm, but when that fails, invoking the same algorithm on the
1620-
/// buffer pointer passed into your closure lets you trade safety for speed.
1621-
///
1622-
/// The following example shows how modifying the contents of the
1623-
/// `UnsafeMutableBufferPointer` argument to `body` alters the contents of
1624-
/// the array:
1625-
///
1626-
/// var numbers = [1, 2, 3, 4, 5]
1627-
/// numbers.withUnsafeMutableBufferPointer { buffer in
1628-
/// for i in stride(from: buffer.startIndex, to: buffer.endIndex - 1, by: 2) {
1629-
/// buffer.swapAt(i, i + 1)
1630-
/// }
1631-
/// }
1632-
/// print(numbers)
1633-
/// // Prints "[2, 1, 4, 3, 5]"
1634-
///
1635-
/// The pointer passed as an argument to `body` is valid only during the
1636-
/// execution of `withUnsafeMutableBufferPointer(_:)`. Do not store or
1637-
/// return the pointer for later use.
1638-
///
1639-
/// - Warning: Do not rely on anything about the array that is the target of
1640-
/// this method during execution of the `body` closure; it might not
1641-
/// appear to have its correct value. Instead, use only the
1642-
/// `UnsafeMutableBufferPointer` argument to `body`.
1643-
///
1644-
/// - Parameter body: A closure with an `UnsafeMutableBufferPointer`
1645-
/// parameter that points to the contiguous storage for the array.
1646-
/// If no such storage exists, it is created. If `body` has a return value, that value is also
1647-
/// used as the return value for the `withUnsafeMutableBufferPointer(_:)`
1648-
/// method. The pointer argument is valid only for the duration of the
1649-
/// method's execution.
1650-
/// - Returns: The return value, if any, of the `body` closure parameter.
1615+
// Superseded by the typed-throws version of this function, but retained
1616+
// for ABI reasons.
16511617
@_semantics("array.withUnsafeMutableBufferPointer")
16521618
@_effects(notEscaping self.value**)
16531619
@inlinable // FIXME(inline-always)
16541620
@inline(__always) // Performance: This method should get inlined into the
16551621
// caller such that we can combine the partial apply with the apply in this
16561622
// function saving on allocating a closure context. This becomes unnecessary
16571623
// once we allocate noescape closures on the stack.
1658-
public mutating func withUnsafeMutableBufferPointer<R>(
1624+
@_silgen_name("$sSa30withUnsafeMutableBufferPointeryqd__qd__SryxGzKXEKlF")
1625+
mutating func __abi_withUnsafeMutableBufferPointer<R>(
16591626
_ body: (inout UnsafeMutableBufferPointer<Element>) throws -> R
16601627
) rethrows -> R {
16611628
_makeMutableAndUnique()
@@ -1679,6 +1646,37 @@ extension Array {
16791646
return try body(&inoutBufferPointer)
16801647
}
16811648

1649+
@_semantics("array.withUnsafeMutableBufferPointer")
1650+
@_effects(notEscaping self.value**)
1651+
@_alwaysEmitIntoClient
1652+
@inline(__always) // Performance: This method should get inlined into the
1653+
// caller such that we can combine the partial apply with the apply in this
1654+
// function saving on allocating a closure context. This becomes unnecessary
1655+
// once we allocate noescape closures on the stack.
1656+
public mutating func withUnsafeMutableBufferPointer<R, E>(
1657+
_ body: (inout UnsafeMutableBufferPointer<Element>) throws(E) -> R
1658+
) throws(E) -> R {
1659+
_makeMutableAndUnique()
1660+
let count = _buffer.mutableCount
1661+
1662+
// Create an UnsafeBufferPointer that we can pass to body
1663+
let pointer = _buffer.mutableFirstElementAddress
1664+
var inoutBufferPointer = UnsafeMutableBufferPointer(
1665+
start: pointer, count: count)
1666+
1667+
defer {
1668+
_precondition(
1669+
inoutBufferPointer.baseAddress == pointer &&
1670+
inoutBufferPointer.count == count,
1671+
"Array withUnsafeMutableBufferPointer: replacing the buffer is not allowed")
1672+
_endMutation()
1673+
_fixLifetime(self)
1674+
}
1675+
1676+
// Invoke the body.
1677+
return try body(&inoutBufferPointer)
1678+
}
1679+
16821680
@inlinable
16831681
public __consuming func _copyContents(
16841682
initializing buffer: UnsafeMutableBufferPointer<Element>

stdlib/public/core/ArrayBuffer.swift

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -597,14 +597,25 @@ extension _ArrayBuffer {
597597
return try ContiguousArray(self).withUnsafeBufferPointer(body)
598598
}
599599

600+
// Superseded by the typed-throws version of this function, but retained
601+
// for ABI reasons.
602+
@inlinable
603+
@_silgen_name("$ss12_ArrayBufferV017withUnsafeMutableB7Pointeryqd__qd__SryxGKXEKlF")
604+
internal mutating func __abi_withUnsafeMutableBufferPointer<R>(
605+
_ body: (UnsafeMutableBufferPointer<Element>) throws -> R
606+
) rethrows -> R {
607+
return try withUnsafeMutableBufferPointer(body)
608+
}
609+
600610
/// Call `body(p)`, where `p` is an `UnsafeMutableBufferPointer`
601611
/// over the underlying contiguous storage.
602612
///
603613
/// - Precondition: Such contiguous storage exists or the buffer is empty.
604614
@inlinable
605-
internal mutating func withUnsafeMutableBufferPointer<R>(
606-
_ body: (UnsafeMutableBufferPointer<Element>) throws -> R
607-
) rethrows -> R {
615+
@_alwaysEmitIntoClient
616+
internal mutating func withUnsafeMutableBufferPointer<R, E>(
617+
_ body: (UnsafeMutableBufferPointer<Element>) throws(E) -> R
618+
) throws(E) -> R {
608619
_internalInvariant(
609620
_isNative || count == 0,
610621
"Array is bridging an opaque NSArray; can't get a pointer to the elements"

stdlib/public/core/ArrayBufferProtocol.swift

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,13 +90,20 @@ where Indices == Range<Int> {
9090
_ body: (UnsafeBufferPointer<Element>) throws(E) -> R
9191
) throws(E) -> R
9292

93+
// Superseded by the typed-throws version of this function, but retained
94+
// for ABI reasons.
95+
mutating func withUnsafeMutableBufferPointer<R>(
96+
_ body: (UnsafeMutableBufferPointer<Element>) throws -> R
97+
) rethrows -> R
98+
9399
/// Call `body(p)`, where `p` is an `UnsafeMutableBufferPointer`
94100
/// over the underlying contiguous storage.
95101
///
96102
/// - Precondition: Such contiguous storage exists or the buffer is empty.
97-
mutating func withUnsafeMutableBufferPointer<R>(
98-
_ body: (UnsafeMutableBufferPointer<Element>) throws -> R
99-
) rethrows -> R
103+
@available(SwiftStdlib 6.1, *)
104+
mutating func withUnsafeMutableBufferPointer<R, E>(
105+
_ body: (UnsafeMutableBufferPointer<Element>) throws(E) -> R
106+
) throws(E) -> R
100107

101108
/// The number of elements the buffer stores.
102109
override var count: Int { get set }

stdlib/public/core/ArraySlice.swift

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,6 +1211,21 @@ extension ArraySlice {
12111211
return try _buffer.withUnsafeBufferPointer(body)
12121212
}
12131213

1214+
// Superseded by the typed-throws version of this function, but retained
1215+
// for ABI reasons.
1216+
@_semantics("array.withUnsafeMutableBufferPointer")
1217+
@inlinable // FIXME(inline-always)
1218+
@inline(__always) // Performance: This method should get inlined into the
1219+
// caller such that we can combine the partial apply with the apply in this
1220+
// function saving on allocating a closure context. This becomes unnecessary
1221+
// once we allocate noescape closures on the stack.
1222+
@_silgen_name("$ss10ArraySliceV30withUnsafeMutableBufferPointeryqd__qd__SryxGzKXEKlF")
1223+
mutating func __abi_withUnsafeMutableBufferPointer<R>(
1224+
_ body: (inout UnsafeMutableBufferPointer<Element>) throws -> R
1225+
) rethrows -> R {
1226+
return try withUnsafeMutableBufferPointer(body)
1227+
}
1228+
12141229
/// Calls the given closure with a pointer to the array's mutable contiguous
12151230
/// storage.
12161231
///
@@ -1248,14 +1263,14 @@ extension ArraySlice {
12481263
/// method's execution.
12491264
/// - Returns: The return value, if any, of the `body` closure parameter.
12501265
@_semantics("array.withUnsafeMutableBufferPointer")
1251-
@inlinable // FIXME(inline-always)
1266+
@_alwaysEmitIntoClient
12521267
@inline(__always) // Performance: This method should get inlined into the
12531268
// caller such that we can combine the partial apply with the apply in this
12541269
// function saving on allocating a closure context. This becomes unnecessary
12551270
// once we allocate noescape closures on the stack.
1256-
public mutating func withUnsafeMutableBufferPointer<R>(
1257-
_ body: (inout UnsafeMutableBufferPointer<Element>) throws -> R
1258-
) rethrows -> R {
1271+
public mutating func withUnsafeMutableBufferPointer<R, E>(
1272+
_ body: (inout UnsafeMutableBufferPointer<Element>) throws(E) -> R
1273+
) throws(E) -> R {
12591274
let count = self.count
12601275
// Ensure unique storage
12611276
_makeMutableAndUnique()

stdlib/public/core/ContiguousArray.swift

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1152,6 +1152,21 @@ extension ContiguousArray {
11521152
return try _buffer.withUnsafeBufferPointer(body)
11531153
}
11541154

1155+
// Superseded by the typed-throws version of this function, but retained
1156+
// for ABI reasons.
1157+
@_semantics("array.withUnsafeMutableBufferPointer")
1158+
@inlinable // FIXME(inline-always)
1159+
@inline(__always) // Performance: This method should get inlined into the
1160+
// caller such that we can combine the partial apply with the apply in this
1161+
// function saving on allocating a closure context. This becomes unnecessary
1162+
// once we allocate noescape closures on the stack.
1163+
@_silgen_name("$ss15ContiguousArrayV30withUnsafeMutableBufferPointeryqd__qd__SryxGzKXEKlF")
1164+
mutating func __abi_withUnsafeMutableBufferPointer<R>(
1165+
_ body: (inout UnsafeMutableBufferPointer<Element>) throws -> R
1166+
) rethrows -> R {
1167+
return try withUnsafeMutableBufferPointer(body)
1168+
}
1169+
11551170
/// Calls the given closure with a pointer to the array's mutable contiguous
11561171
/// storage.
11571172
///
@@ -1189,14 +1204,14 @@ extension ContiguousArray {
11891204
/// method's execution.
11901205
/// - Returns: The return value, if any, of the `body` closure parameter.
11911206
@_semantics("array.withUnsafeMutableBufferPointer")
1192-
@inlinable // FIXME(inline-always)
1207+
@_alwaysEmitIntoClient
11931208
@inline(__always) // Performance: This method should get inlined into the
11941209
// caller such that we can combine the partial apply with the apply in this
11951210
// function saving on allocating a closure context. This becomes unnecessary
11961211
// once we allocate noescape closures on the stack.
1197-
public mutating func withUnsafeMutableBufferPointer<R>(
1198-
_ body: (inout UnsafeMutableBufferPointer<Element>) throws -> R
1199-
) rethrows -> R {
1212+
public mutating func withUnsafeMutableBufferPointer<R, E>(
1213+
_ body: (inout UnsafeMutableBufferPointer<Element>) throws(E) -> R
1214+
) throws(E) -> R {
12001215
_makeMutableAndUnique()
12011216
let count = _buffer.mutableCount
12021217

stdlib/public/core/ContiguousArrayBuffer.swift

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -467,17 +467,29 @@ internal struct _ContiguousArrayBuffer<Element>: _ArrayBufferProtocol {
467467
count: count))
468468
}
469469

470-
/// Call `body(p)`, where `p` is an `UnsafeMutableBufferPointer`
471-
/// over the underlying contiguous storage.
470+
// Superseded by the typed-throws version of this function, but retained
471+
// for ABI reasons.
472472
@inlinable
473-
internal mutating func withUnsafeMutableBufferPointer<R>(
473+
@_silgen_name("$ss22_ContiguousArrayBufferV017withUnsafeMutableC7Pointeryqd__qd__SryxGKXEKlF")
474+
internal mutating func __abi_withUnsafeMutableBufferPointer<R>(
474475
_ body: (UnsafeMutableBufferPointer<Element>) throws -> R
475476
) rethrows -> R {
476477
defer { _fixLifetime(self) }
477478
return try body(
478479
UnsafeMutableBufferPointer(start: firstElementAddress, count: count))
479480
}
480481

482+
/// Call `body(p)`, where `p` is an `UnsafeMutableBufferPointer`
483+
/// over the underlying contiguous storage.
484+
@_alwaysEmitIntoClient
485+
internal mutating func withUnsafeMutableBufferPointer<R, E>(
486+
_ body: (UnsafeMutableBufferPointer<Element>) throws(E) -> R
487+
) throws(E) -> R {
488+
defer { _fixLifetime(self) }
489+
return try body(
490+
UnsafeMutableBufferPointer(start: firstElementAddress, count: count))
491+
}
492+
481493
//===--- _ArrayBufferProtocol conformance -----------------------------------===//
482494
/// Create an empty buffer.
483495
@inlinable

stdlib/public/core/SliceBuffer.swift

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -453,17 +453,29 @@ internal struct _SliceBuffer<Element>
453453
count: count))
454454
}
455455

456-
/// Call `body(p)`, where `p` is an `UnsafeMutableBufferPointer`
457-
/// over the underlying contiguous storage.
456+
// Superseded by the typed-throws version of this function, but retained
457+
// for ABI reasons.
458458
@inlinable
459-
internal mutating func withUnsafeMutableBufferPointer<R>(
459+
@_silgen_name("$ss12_SliceBufferV017withUnsafeMutableB7Pointeryqd__qd__SryxGKXEKlF")
460+
internal mutating func __abi_withUnsafeMutableBufferPointer<R>(
460461
_ body: (UnsafeMutableBufferPointer<Element>) throws -> R
461462
) rethrows -> R {
462463
defer { _fixLifetime(self) }
463464
return try body(
464465
UnsafeMutableBufferPointer(start: firstElementAddress, count: count))
465466
}
466467

468+
/// Call `body(p)`, where `p` is an `UnsafeMutableBufferPointer`
469+
/// over the underlying contiguous storage.
470+
@_alwaysEmitIntoClient
471+
internal mutating func withUnsafeMutableBufferPointer<R, E>(
472+
_ body: (UnsafeMutableBufferPointer<Element>) throws(E) -> R
473+
) throws(E) -> R {
474+
defer { _fixLifetime(self) }
475+
return try body(
476+
UnsafeMutableBufferPointer(start: firstElementAddress, count: count))
477+
}
478+
467479
@inlinable
468480
internal func unsafeCastElements<T>(to type: T.Type) -> _SliceBuffer<T> {
469481
_internalInvariant(_isClassOrObjCExistential(T.self))

test/abi/macOS/arm64/stdlib.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -582,9 +582,14 @@ Added: _$sSS20_immortalCocoaString5count8encodingSSyXl_Sixmtcs16_UnicodeEncoding
582582
// Swift._stdlib_isVariantOSVersionAtLeast(Builtin.Word, Builtin.Word, Builtin.Word) -> Builtin.Int1
583583
Added: _$ss33_stdlib_isVariantOSVersionAtLeastyBi1_Bw_BwBwtF
584584

585-
// Typed throws for withUnsafePointer operations.
585+
// Typed throws for withUnsafeBufferPointer operations.
586586
Added: _$ss12_ArrayBufferV010withUnsafeB7Pointeryqd__qd__SRyxGqd_0_YKXEqd_0_YKs5ErrorRd_0_r0_lF
587587
Added: _$ss12_SliceBufferV010withUnsafeB7Pointeryqd__qd__SRyxGqd_0_YKXEqd_0_YKs5ErrorRd_0_r0_lF
588588
Added: _$ss20_ArrayBufferProtocolP010withUnsafeB7Pointeryqd__qd__SRy7ElementQzGqd_0_YKXEqd_0_YKs5ErrorRd_0_r0_lFTj
589589
Added: _$ss20_ArrayBufferProtocolP010withUnsafeB7Pointeryqd__qd__SRy7ElementQzGqd_0_YKXEqd_0_YKs5ErrorRd_0_r0_lFTq
590590
Added: _$ss22_ContiguousArrayBufferV010withUnsafeC7Pointeryqd__qd__SRyxGqd_0_YKXEqd_0_YKs5ErrorRd_0_r0_lF
591+
592+
593+
// Typed throws for withUnsafeMutableBufferPointer operations.
594+
Added: _$ss20_ArrayBufferProtocolP017withUnsafeMutableB7Pointeryqd__qd__Sry7ElementQzGqd_0_YKXEqd_0_YKs5ErrorRd_0_r0_lFTj
595+
Added: _$ss20_ArrayBufferProtocolP017withUnsafeMutableB7Pointeryqd__qd__Sry7ElementQzGqd_0_YKXEqd_0_YKs5ErrorRd_0_r0_lFTq

test/abi/macOS/x86_64/stdlib.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -582,8 +582,13 @@ Added: _$sSS20_immortalCocoaString5count8encodingSSyXl_Sixmtcs16_UnicodeEncoding
582582
// Swift._stdlib_isVariantOSVersionAtLeast(Builtin.Word, Builtin.Word, Builtin.Word) -> Builtin.Int1
583583
Added: _$ss33_stdlib_isVariantOSVersionAtLeastyBi1_Bw_BwBwtF
584584

585-
// Typed throws for withUnsafePointer operations.
585+
// Typed throws for withUnsafeBufferPointer operations.
586586
Added: _$ss12_ArrayBufferV010withUnsafeB7Pointeryqd__qd__SRyxGqd_0_YKXEqd_0_YKs5ErrorRd_0_r0_lF
587587
Added: _$ss12_SliceBufferV010withUnsafeB7Pointeryqd__qd__SRyxGqd_0_YKXEqd_0_YKs5ErrorRd_0_r0_lF
588588
Added: _$ss20_ArrayBufferProtocolP010withUnsafeB7Pointeryqd__qd__SRy7ElementQzGqd_0_YKXEqd_0_YKs5ErrorRd_0_r0_lFTj
589589
Added: _$ss22_ContiguousArrayBufferV010withUnsafeC7Pointeryqd__qd__SRyxGqd_0_YKXEqd_0_YKs5ErrorRd_0_r0_lF
590+
Added: _$ss20_ArrayBufferProtocolP010withUnsafeB7Pointeryqd__qd__SRy7ElementQzGqd_0_YKXEqd_0_YKs5ErrorRd_0_r0_lFTq
591+
592+
// Typed throws for withUnsafeMutableBufferPointer operations.
593+
Added: _$ss20_ArrayBufferProtocolP017withUnsafeMutableB7Pointeryqd__qd__Sry7ElementQzGqd_0_YKXEqd_0_YKs5ErrorRd_0_r0_lFTj
594+
Added: _$ss20_ArrayBufferProtocolP017withUnsafeMutableB7Pointeryqd__qd__Sry7ElementQzGqd_0_YKXEqd_0_YKs5ErrorRd_0_r0_lFTq

0 commit comments

Comments
 (0)