Skip to content

Commit 73ecefd

Browse files
authored
Merge pull request #75913 from DougGregor/typed-throws-with-unsafe-buffer-ptr
Adopt typed throws in withUnsafe(Mutable)BufferPointer
2 parents 0e853a3 + 2e9ab88 commit 73ecefd

18 files changed

+757
-406
lines changed

stdlib/public/core/Array.swift

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1565,6 +1565,16 @@ extension Array {
15651565
initializingWith: initializer)
15661566
}
15671567

1568+
// Superseded by the typed-throws version of this function, but retained
1569+
// for ABI reasons.
1570+
@usableFromInline
1571+
@_disfavoredOverload
1572+
func withUnsafeBufferPointer<R>(
1573+
_ body: (UnsafeBufferPointer<Element>) throws -> R
1574+
) rethrows -> R {
1575+
return try _buffer.withUnsafeBufferPointer(body)
1576+
}
1577+
15681578
/// Calls a closure with a pointer to the array's contiguous storage.
15691579
///
15701580
/// Often, the optimizer can eliminate bounds checks within an array
@@ -1594,13 +1604,44 @@ extension Array {
15941604
/// for the `withUnsafeBufferPointer(_:)` method. The pointer argument is
15951605
/// valid only for the duration of the method's execution.
15961606
/// - Returns: The return value, if any, of the `body` closure parameter.
1597-
@inlinable
1598-
public func withUnsafeBufferPointer<R>(
1599-
_ body: (UnsafeBufferPointer<Element>) throws -> R
1600-
) rethrows -> R {
1607+
@_alwaysEmitIntoClient
1608+
public func withUnsafeBufferPointer<R, E>(
1609+
_ body: (UnsafeBufferPointer<Element>) throws(E) -> R
1610+
) throws(E) -> R {
16011611
return try _buffer.withUnsafeBufferPointer(body)
16021612
}
16031613

1614+
// Superseded by the typed-throws version of this function, but retained
1615+
// for ABI reasons.
1616+
@_semantics("array.withUnsafeMutableBufferPointer")
1617+
@_effects(notEscaping self.value**)
1618+
@usableFromInline
1619+
@inline(__always)
1620+
@_silgen_name("$sSa30withUnsafeMutableBufferPointeryqd__qd__SryxGzKXEKlF")
1621+
mutating func __abi_withUnsafeMutableBufferPointer<R>(
1622+
_ body: (inout UnsafeMutableBufferPointer<Element>) throws -> R
1623+
) rethrows -> R {
1624+
_makeMutableAndUnique()
1625+
let count = _buffer.mutableCount
1626+
1627+
// Create an UnsafeBufferPointer that we can pass to body
1628+
let pointer = _buffer.mutableFirstElementAddress
1629+
var inoutBufferPointer = UnsafeMutableBufferPointer(
1630+
start: pointer, count: count)
1631+
1632+
defer {
1633+
_precondition(
1634+
inoutBufferPointer.baseAddress == pointer &&
1635+
inoutBufferPointer.count == count,
1636+
"Array withUnsafeMutableBufferPointer: replacing the buffer is not allowed")
1637+
_endMutation()
1638+
_fixLifetime(self)
1639+
}
1640+
1641+
// Invoke the body.
1642+
return try body(&inoutBufferPointer)
1643+
}
1644+
16041645
/// Calls the given closure with a pointer to the array's mutable contiguous
16051646
/// storage.
16061647
///
@@ -1639,14 +1680,14 @@ extension Array {
16391680
/// - Returns: The return value, if any, of the `body` closure parameter.
16401681
@_semantics("array.withUnsafeMutableBufferPointer")
16411682
@_effects(notEscaping self.value**)
1642-
@inlinable // FIXME(inline-always)
1683+
@_alwaysEmitIntoClient
16431684
@inline(__always) // Performance: This method should get inlined into the
16441685
// caller such that we can combine the partial apply with the apply in this
16451686
// function saving on allocating a closure context. This becomes unnecessary
16461687
// once we allocate noescape closures on the stack.
1647-
public mutating func withUnsafeMutableBufferPointer<R>(
1648-
_ body: (inout UnsafeMutableBufferPointer<Element>) throws -> R
1649-
) rethrows -> R {
1688+
public mutating func withUnsafeMutableBufferPointer<R, E>(
1689+
_ body: (inout UnsafeMutableBufferPointer<Element>) throws(E) -> R
1690+
) throws(E) -> R {
16501691
_makeMutableAndUnique()
16511692
let count = _buffer.mutableCount
16521693

stdlib/public/core/ArrayBuffer.swift

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -567,29 +567,54 @@ extension _ArrayBuffer {
567567
}
568568
}
569569

570+
// Superseded by the typed-throws version of this function, but retained
571+
// for ABI reasons.
572+
@usableFromInline
573+
@_silgen_name("$ss12_ArrayBufferV010withUnsafeB7Pointeryqd__qd__SRyxGKXEKlF")
574+
internal func __abi_withUnsafeBufferPointer<R>(
575+
_ body: (UnsafeBufferPointer<Element>) throws -> R
576+
) rethrows -> R {
577+
if _fastPath(_isNative) {
578+
defer { _fixLifetime(self) }
579+
return try body(
580+
UnsafeBufferPointer(start: firstElementAddress, count: count))
581+
}
582+
return try ContiguousArray(self).withUnsafeBufferPointer(body)
583+
}
584+
570585
/// Call `body(p)`, where `p` is an `UnsafeBufferPointer` over the
571586
/// underlying contiguous storage. If no such storage exists, it is
572587
/// created on-demand.
573-
@inlinable
574-
internal func withUnsafeBufferPointer<R>(
575-
_ body: (UnsafeBufferPointer<Element>) throws -> R
576-
) rethrows -> R {
588+
@_alwaysEmitIntoClient
589+
internal func withUnsafeBufferPointer<R, E>(
590+
_ body: (UnsafeBufferPointer<Element>) throws(E) -> R
591+
) throws(E) -> R {
577592
if _fastPath(_isNative) {
578593
defer { _fixLifetime(self) }
579594
return try body(
580595
UnsafeBufferPointer(start: firstElementAddress, count: count))
581596
}
582597
return try ContiguousArray(self).withUnsafeBufferPointer(body)
583598
}
584-
599+
600+
// Superseded by the typed-throws version of this function, but retained
601+
// for ABI reasons.
602+
@usableFromInline
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+
585610
/// Call `body(p)`, where `p` is an `UnsafeMutableBufferPointer`
586611
/// over the underlying contiguous storage.
587612
///
588613
/// - Precondition: Such contiguous storage exists or the buffer is empty.
589-
@inlinable
590-
internal mutating func withUnsafeMutableBufferPointer<R>(
591-
_ body: (UnsafeMutableBufferPointer<Element>) throws -> R
592-
) rethrows -> R {
614+
@_alwaysEmitIntoClient
615+
internal mutating func withUnsafeMutableBufferPointer<R, E>(
616+
_ body: (UnsafeMutableBufferPointer<Element>) throws(E) -> R
617+
) throws(E) -> R {
593618
_internalInvariant(
594619
_isNative || count == 0,
595620
"Array is bridging an opaque NSArray; can't get a pointer to the elements"

stdlib/public/core/ArrayBufferProtocol.swift

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,20 +76,34 @@ where Indices == Range<Int> {
7676
/// Returns a `_SliceBuffer` containing the elements in `bounds`.
7777
subscript(bounds: Range<Int>) -> _SliceBuffer<Element> { get }
7878

79+
// Superseded by the typed-throws version of this function, but retained
80+
// for ABI reasons.
81+
func withUnsafeBufferPointer<R>(
82+
_ body: (UnsafeBufferPointer<Element>) throws -> R
83+
) rethrows -> R
84+
7985
/// Call `body(p)`, where `p` is an `UnsafeBufferPointer` over the
8086
/// underlying contiguous storage. If no such storage exists, it is
8187
/// created on-demand.
82-
func withUnsafeBufferPointer<R>(
83-
_ body: (UnsafeBufferPointer<Element>) throws -> R
88+
@available(SwiftStdlib 6.1, *)
89+
func withUnsafeBufferPointer<R, E>(
90+
_ body: (UnsafeBufferPointer<Element>) throws(E) -> R
91+
) throws(E) -> R
92+
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
8497
) rethrows -> R
8598

8699
/// Call `body(p)`, where `p` is an `UnsafeMutableBufferPointer`
87100
/// over the underlying contiguous storage.
88101
///
89102
/// - Precondition: Such contiguous storage exists or the buffer is empty.
90-
mutating func withUnsafeMutableBufferPointer<R>(
91-
_ body: (UnsafeMutableBufferPointer<Element>) throws -> R
92-
) rethrows -> R
103+
@available(SwiftStdlib 6.1, *)
104+
mutating func withUnsafeMutableBufferPointer<R, E>(
105+
_ body: (UnsafeMutableBufferPointer<Element>) throws(E) -> R
106+
) throws(E) -> R
93107

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

stdlib/public/core/ArraySlice.swift

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,6 +1164,16 @@ extension ArraySlice {
11641164
}
11651165

11661166
extension ArraySlice {
1167+
// Superseded by the typed-throws version of this function, but retained
1168+
// for ABI reasons.
1169+
@usableFromInline
1170+
@_disfavoredOverload
1171+
func withUnsafeBufferPointer<R>(
1172+
_ body: (UnsafeBufferPointer<Element>) throws -> R
1173+
) rethrows -> R {
1174+
return try _buffer.withUnsafeBufferPointer(body)
1175+
}
1176+
11671177
/// Calls a closure with a pointer to the array's contiguous storage.
11681178
///
11691179
/// Often, the optimizer can eliminate bounds checks within an array
@@ -1193,13 +1203,25 @@ extension ArraySlice {
11931203
/// for the `withUnsafeBufferPointer(_:)` method. The pointer argument is
11941204
/// valid only for the duration of the method's execution.
11951205
/// - Returns: The return value, if any, of the `body` closure parameter.
1196-
@inlinable
1197-
public func withUnsafeBufferPointer<R>(
1198-
_ body: (UnsafeBufferPointer<Element>) throws -> R
1199-
) rethrows -> R {
1206+
@_alwaysEmitIntoClient
1207+
public func withUnsafeBufferPointer<R, E>(
1208+
_ body: (UnsafeBufferPointer<Element>) throws(E) -> R
1209+
) throws(E) -> R {
12001210
return try _buffer.withUnsafeBufferPointer(body)
12011211
}
12021212

1213+
// Superseded by the typed-throws version of this function, but retained
1214+
// for ABI reasons.
1215+
@_semantics("array.withUnsafeMutableBufferPointer")
1216+
@usableFromInline
1217+
@inline(__always)
1218+
@_silgen_name("$ss10ArraySliceV30withUnsafeMutableBufferPointeryqd__qd__SryxGzKXEKlF")
1219+
mutating func __abi_withUnsafeMutableBufferPointer<R>(
1220+
_ body: (inout UnsafeMutableBufferPointer<Element>) throws -> R
1221+
) rethrows -> R {
1222+
return try withUnsafeMutableBufferPointer(body)
1223+
}
1224+
12031225
/// Calls the given closure with a pointer to the array's mutable contiguous
12041226
/// storage.
12051227
///
@@ -1237,14 +1259,14 @@ extension ArraySlice {
12371259
/// method's execution.
12381260
/// - Returns: The return value, if any, of the `body` closure parameter.
12391261
@_semantics("array.withUnsafeMutableBufferPointer")
1240-
@inlinable // FIXME(inline-always)
1262+
@_alwaysEmitIntoClient
12411263
@inline(__always) // Performance: This method should get inlined into the
12421264
// caller such that we can combine the partial apply with the apply in this
12431265
// function saving on allocating a closure context. This becomes unnecessary
12441266
// once we allocate noescape closures on the stack.
1245-
public mutating func withUnsafeMutableBufferPointer<R>(
1246-
_ body: (inout UnsafeMutableBufferPointer<Element>) throws -> R
1247-
) rethrows -> R {
1267+
public mutating func withUnsafeMutableBufferPointer<R, E>(
1268+
_ body: (inout UnsafeMutableBufferPointer<Element>) throws(E) -> R
1269+
) throws(E) -> R {
12481270
let count = self.count
12491271
// Ensure unique storage
12501272
_makeMutableAndUnique()

stdlib/public/core/ContiguousArray.swift

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,6 +1105,16 @@ extension ContiguousArray {
11051105
initializingWith: initializer))
11061106
}
11071107

1108+
// Superseded by the typed-throws version of this function, but retained
1109+
// for ABI reasons.
1110+
@usableFromInline
1111+
@_disfavoredOverload
1112+
func withUnsafeBufferPointer<R>(
1113+
_ body: (UnsafeBufferPointer<Element>) throws -> R
1114+
) rethrows -> R {
1115+
return try _buffer.withUnsafeBufferPointer(body)
1116+
}
1117+
11081118
/// Calls a closure with a pointer to the array's contiguous storage.
11091119
///
11101120
/// Often, the optimizer can eliminate bounds checks within an array
@@ -1134,13 +1144,25 @@ extension ContiguousArray {
11341144
/// for the `withUnsafeBufferPointer(_:)` method. The pointer argument is
11351145
/// valid only for the duration of the method's execution.
11361146
/// - Returns: The return value, if any, of the `body` closure parameter.
1137-
@inlinable
1138-
public func withUnsafeBufferPointer<R>(
1139-
_ body: (UnsafeBufferPointer<Element>) throws -> R
1140-
) rethrows -> R {
1147+
@_alwaysEmitIntoClient
1148+
public func withUnsafeBufferPointer<R, E>(
1149+
_ body: (UnsafeBufferPointer<Element>) throws(E) -> R
1150+
) throws(E) -> R {
11411151
return try _buffer.withUnsafeBufferPointer(body)
11421152
}
11431153

1154+
// Superseded by the typed-throws version of this function, but retained
1155+
// for ABI reasons.
1156+
@_semantics("array.withUnsafeMutableBufferPointer")
1157+
@usableFromInline
1158+
@inline(__always)
1159+
@_silgen_name("$ss15ContiguousArrayV30withUnsafeMutableBufferPointeryqd__qd__SryxGzKXEKlF")
1160+
mutating func __abi_withUnsafeMutableBufferPointer<R>(
1161+
_ body: (inout UnsafeMutableBufferPointer<Element>) throws -> R
1162+
) rethrows -> R {
1163+
return try withUnsafeMutableBufferPointer(body)
1164+
}
1165+
11441166
/// Calls the given closure with a pointer to the array's mutable contiguous
11451167
/// storage.
11461168
///
@@ -1178,14 +1200,14 @@ extension ContiguousArray {
11781200
/// method's execution.
11791201
/// - Returns: The return value, if any, of the `body` closure parameter.
11801202
@_semantics("array.withUnsafeMutableBufferPointer")
1181-
@inlinable // FIXME(inline-always)
1203+
@_alwaysEmitIntoClient
11821204
@inline(__always) // Performance: This method should get inlined into the
11831205
// caller such that we can combine the partial apply with the apply in this
11841206
// function saving on allocating a closure context. This becomes unnecessary
11851207
// once we allocate noescape closures on the stack.
1186-
public mutating func withUnsafeMutableBufferPointer<R>(
1187-
_ body: (inout UnsafeMutableBufferPointer<Element>) throws -> R
1188-
) rethrows -> R {
1208+
public mutating func withUnsafeMutableBufferPointer<R, E>(
1209+
_ body: (inout UnsafeMutableBufferPointer<Element>) throws(E) -> R
1210+
) throws(E) -> R {
11891211
_makeMutableAndUnique()
11901212
let count = _buffer.mutableCount
11911213

stdlib/public/core/ContiguousArrayBuffer.swift

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -444,28 +444,52 @@ internal struct _ContiguousArrayBuffer<Element>: _ArrayBufferProtocol {
444444
return firstElementAddress
445445
}
446446

447-
/// Call `body(p)`, where `p` is an `UnsafeBufferPointer` over the
448-
/// underlying contiguous storage.
449-
@inlinable
450-
internal func withUnsafeBufferPointer<R>(
447+
// Superseded by the typed-throws version of this function, but retained
448+
// for ABI reasons.
449+
@usableFromInline
450+
@_silgen_name("$ss22_ContiguousArrayBufferV010withUnsafeC7Pointeryqd__qd__SRyxGKXEKlF")
451+
internal func __abi_withUnsafeBufferPointer<R>(
451452
_ body: (UnsafeBufferPointer<Element>) throws -> R
452453
) rethrows -> R {
453454
defer { _fixLifetime(self) }
454455
return try body(UnsafeBufferPointer(start: firstElementAddress,
455456
count: count))
456457
}
457458

458-
/// Call `body(p)`, where `p` is an `UnsafeMutableBufferPointer`
459-
/// over the underlying contiguous storage.
460-
@inlinable
461-
internal mutating func withUnsafeMutableBufferPointer<R>(
459+
/// Call `body(p)`, where `p` is an `UnsafeBufferPointer` over the
460+
/// underlying contiguous storage.
461+
@_alwaysEmitIntoClient
462+
internal func withUnsafeBufferPointer<R, E>(
463+
_ body: (UnsafeBufferPointer<Element>) throws(E) -> R
464+
) throws(E) -> R {
465+
defer { _fixLifetime(self) }
466+
return try body(UnsafeBufferPointer(start: firstElementAddress,
467+
count: count))
468+
}
469+
470+
// Superseded by the typed-throws version of this function, but retained
471+
// for ABI reasons.
472+
@usableFromInline
473+
@_silgen_name("$ss22_ContiguousArrayBufferV017withUnsafeMutableC7Pointeryqd__qd__SryxGKXEKlF")
474+
internal mutating func __abi_withUnsafeMutableBufferPointer<R>(
462475
_ body: (UnsafeMutableBufferPointer<Element>) throws -> R
463476
) rethrows -> R {
464477
defer { _fixLifetime(self) }
465478
return try body(
466479
UnsafeMutableBufferPointer(start: firstElementAddress, count: count))
467480
}
468481

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+
469493
//===--- _ArrayBufferProtocol conformance -----------------------------------===//
470494
/// Create an empty buffer.
471495
@inlinable

0 commit comments

Comments
 (0)