Skip to content

Commit c9b1ab8

Browse files
authored
Merge pull request #79650 from glessard/rdar138440979-MutableSpan
[SE-0467] MutableSpan, with mutableSpan properties to Array, ArraySlice and ContiguousArray.
2 parents b63ed2b + 32e1ea1 commit c9b1ab8

14 files changed

+2905
-43
lines changed

Runtimes/Core/core/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ add_library(swiftCore
152152
Sort.swift
153153
Span/Span.swift
154154
Span/RawSpan.swift
155+
Span/MutableSpan.swift
156+
Span/MutableRawSpan.swift
155157
StaticString.swift
156158
StaticPrint.swift
157159
Stride.swift

stdlib/public/core/Array.swift

+37-19
Original file line numberDiff line numberDiff line change
@@ -1428,25 +1428,6 @@ extension Array: RangeReplaceableCollection {
14281428
}
14291429
}
14301430

1431-
@available(SwiftStdlib 6.2, *)
1432-
public var span: Span<Element> {
1433-
@lifetime(borrow self)
1434-
@_alwaysEmitIntoClient
1435-
borrowing get {
1436-
#if _runtime(_ObjC)
1437-
if _slowPath(!_buffer._isNative) {
1438-
let buffer = _buffer.getOrAllocateAssociatedObjectBuffer()
1439-
let (pointer, count) = unsafe (buffer.firstElementAddress, buffer.count)
1440-
let span = unsafe Span(_unsafeStart: pointer, count: count)
1441-
return unsafe _overrideLifetime(span, borrowing: self)
1442-
}
1443-
#endif
1444-
let (pointer, count) = unsafe (_buffer.firstElementAddress, _buffer.count)
1445-
let span = unsafe Span(_unsafeStart: pointer, count: count)
1446-
return unsafe _overrideLifetime(span, borrowing: self)
1447-
}
1448-
}
1449-
14501431
@inlinable
14511432
public __consuming func _copyToContiguousArray() -> ContiguousArray<Element> {
14521433
if let n = _buffer.requestNativeBuffer() {
@@ -1630,6 +1611,27 @@ extension Array {
16301611
return try unsafe _buffer.withUnsafeBufferPointer(body)
16311612
}
16321613

1614+
@available(SwiftStdlib 6.2, *)
1615+
public var span: Span<Element> {
1616+
@lifetime(borrow self)
1617+
@_alwaysEmitIntoClient
1618+
borrowing get {
1619+
#if _runtime(_ObjC)
1620+
if _slowPath(!_buffer._isNative) {
1621+
let buffer = _buffer.getOrAllocateAssociatedObjectBuffer()
1622+
let pointer = unsafe buffer.firstElementAddress
1623+
let count = buffer.immutableCount
1624+
let span = unsafe Span(_unsafeStart: pointer, count: count)
1625+
return unsafe _overrideLifetime(span, borrowing: self)
1626+
}
1627+
#endif
1628+
let pointer = unsafe _buffer.firstElementAddress
1629+
let count = _buffer.immutableCount
1630+
let span = unsafe Span(_unsafeStart: pointer, count: count)
1631+
return unsafe _overrideLifetime(span, borrowing: self)
1632+
}
1633+
}
1634+
16331635
// Superseded by the typed-throws version of this function, but retained
16341636
// for ABI reasons.
16351637
@_semantics("array.withUnsafeMutableBufferPointer")
@@ -1728,6 +1730,22 @@ extension Array {
17281730
return try unsafe body(&inoutBufferPointer)
17291731
}
17301732

1733+
@available(SwiftStdlib 6.2, *)
1734+
public var mutableSpan: MutableSpan<Element> {
1735+
@lifetime(/*inout*/borrow self)
1736+
@_alwaysEmitIntoClient
1737+
mutating get {
1738+
_makeMutableAndUnique()
1739+
// NOTE: We don't have the ability to schedule a call to
1740+
// ContiguousArrayBuffer.endCOWMutation().
1741+
// rdar://146785284 (lifetime analysis for end of mutation)
1742+
let pointer = unsafe _buffer.firstElementAddress
1743+
let count = _buffer.mutableCount
1744+
let span = unsafe MutableSpan(_unsafeStart: pointer, count: count)
1745+
return unsafe _overrideLifetime(span, mutating: &self)
1746+
}
1747+
}
1748+
17311749
@inlinable
17321750
public __consuming func _copyContents(
17331751
initializing buffer: UnsafeMutableBufferPointer<Element>

stdlib/public/core/ArraySlice.swift

+26-11
Original file line numberDiff line numberDiff line change
@@ -1116,17 +1116,6 @@ extension ArraySlice: RangeReplaceableCollection {
11161116
}
11171117
}
11181118

1119-
@available(SwiftStdlib 6.2, *)
1120-
public var span: Span<Element> {
1121-
@lifetime(borrow self)
1122-
@_alwaysEmitIntoClient
1123-
borrowing get {
1124-
let (pointer, count) = (_buffer.firstElementAddress, _buffer.count)
1125-
let span = unsafe Span(_unsafeStart: pointer, count: count)
1126-
return unsafe _overrideLifetime(span, borrowing: self)
1127-
}
1128-
}
1129-
11301119
@inlinable
11311120
public __consuming func _copyToContiguousArray() -> ContiguousArray<Element> {
11321121
if let n = _buffer.requestNativeBuffer() {
@@ -1221,6 +1210,17 @@ extension ArraySlice {
12211210
return try _buffer.withUnsafeBufferPointer(body)
12221211
}
12231212

1213+
@available(SwiftStdlib 6.2, *)
1214+
public var span: Span<Element> {
1215+
@lifetime(borrow self)
1216+
@_alwaysEmitIntoClient
1217+
borrowing get {
1218+
let (pointer, count) = unsafe (_buffer.firstElementAddress, _buffer.count)
1219+
let span = unsafe Span(_unsafeStart: pointer, count: count)
1220+
return unsafe _overrideLifetime(span, borrowing: self)
1221+
}
1222+
}
1223+
12241224
// Superseded by the typed-throws version of this function, but retained
12251225
// for ABI reasons.
12261226
@_semantics("array.withUnsafeMutableBufferPointer")
@@ -1300,6 +1300,21 @@ extension ArraySlice {
13001300
return try unsafe body(&inoutBufferPointer)
13011301
}
13021302

1303+
@available(SwiftStdlib 6.2, *)
1304+
public var mutableSpan: MutableSpan<Element> {
1305+
@lifetime(/*inout*/borrow self)
1306+
@_alwaysEmitIntoClient
1307+
mutating get {
1308+
_makeMutableAndUnique()
1309+
// NOTE: We don't have the ability to schedule a call to
1310+
// ContiguousArrayBuffer.endCOWMutation().
1311+
// rdar://146785284 (lifetime analysis for end of mutation)
1312+
let (pointer, count) = unsafe (_buffer.firstElementAddress, _buffer.count)
1313+
let span = unsafe MutableSpan(_unsafeStart: pointer, count: count)
1314+
return unsafe _overrideLifetime(span, mutating: &self)
1315+
}
1316+
}
1317+
13031318
@inlinable
13041319
public __consuming func _copyContents(
13051320
initializing buffer: UnsafeMutableBufferPointer<Element>

stdlib/public/core/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,8 @@ split_embedded_sources(
157157
EMBEDDED Slice.swift
158158
EMBEDDED SmallString.swift
159159
EMBEDDED Sort.swift
160+
EMBEDDED Span/MutableRawSpan.swift
161+
EMBEDDED Span/MutableSpan.swift
160162
EMBEDDED Span/RawSpan.swift
161163
EMBEDDED Span/Span.swift
162164
EMBEDDED StaticString.swift

stdlib/public/core/ContiguousArray.swift

+28-11
Original file line numberDiff line numberDiff line change
@@ -1021,17 +1021,6 @@ extension ContiguousArray: RangeReplaceableCollection {
10211021
}
10221022
}
10231023

1024-
@available(SwiftStdlib 6.2, *)
1025-
public var span: Span<Element> {
1026-
@lifetime(borrow self)
1027-
@_alwaysEmitIntoClient
1028-
borrowing get {
1029-
let (pointer, count) = unsafe (_buffer.firstElementAddress, _buffer.count)
1030-
let span = unsafe Span(_unsafeStart: pointer, count: count)
1031-
return unsafe _overrideLifetime(span, borrowing: self)
1032-
}
1033-
}
1034-
10351024
@inlinable
10361025
public __consuming func _copyToContiguousArray() -> ContiguousArray<Element> {
10371026
if let n = _buffer.requestNativeBuffer() {
@@ -1163,6 +1152,18 @@ extension ContiguousArray {
11631152
return try unsafe _buffer.withUnsafeBufferPointer(body)
11641153
}
11651154

1155+
@available(SwiftStdlib 6.2, *)
1156+
public var span: Span<Element> {
1157+
@lifetime(borrow self)
1158+
@_alwaysEmitIntoClient
1159+
borrowing get {
1160+
let pointer = unsafe _buffer.firstElementAddress
1161+
let count = _buffer.immutableCount
1162+
let span = unsafe Span(_unsafeStart: pointer, count: count)
1163+
return unsafe _overrideLifetime(span, borrowing: self)
1164+
}
1165+
}
1166+
11661167
// Superseded by the typed-throws version of this function, but retained
11671168
// for ABI reasons.
11681169
@_semantics("array.withUnsafeMutableBufferPointer")
@@ -1241,6 +1242,22 @@ extension ContiguousArray {
12411242
return try unsafe body(&inoutBufferPointer)
12421243
}
12431244

1245+
@available(SwiftStdlib 6.2, *)
1246+
public var mutableSpan: MutableSpan<Element> {
1247+
@lifetime(/*inout*/borrow self)
1248+
@_alwaysEmitIntoClient
1249+
mutating get {
1250+
_makeMutableAndUnique()
1251+
// NOTE: We don't have the ability to schedule a call to
1252+
// ContiguousArrayBuffer.endCOWMutation().
1253+
// rdar://146785284 (lifetime analysis for end of mutation)
1254+
let pointer = unsafe _buffer.firstElementAddress
1255+
let count = _buffer.mutableCount
1256+
let span = unsafe MutableSpan(_unsafeStart: pointer, count: count)
1257+
return unsafe _overrideLifetime(span, mutating: &self)
1258+
}
1259+
}
1260+
12441261
@inlinable
12451262
public __consuming func _copyContents(
12461263
initializing buffer: UnsafeMutableBufferPointer<Element>

stdlib/public/core/GroupInfo.json

+2
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@
200200
"UnsafeRawBufferPointer.swift"
201201
],
202202
"Span": [
203+
"MutableRawSpan.swift",
204+
"MutableSpan.swift",
203205
"RawSpan.swift",
204206
"Span.swift"
205207
],

stdlib/public/core/LifetimeManager.swift

+19
Original file line numberDiff line numberDiff line change
@@ -317,3 +317,22 @@ internal func _overrideLifetime<
317317
// should be expressed by a builtin that is hidden within the function body.
318318
dependent
319319
}
320+
321+
/// Unsafely discard any lifetime dependency on the `dependent` argument.
322+
/// Return a value identical to `dependent` with a lifetime dependency
323+
/// on the caller's exclusive borrow scope of the `source` argument.
324+
@unsafe
325+
@_unsafeNonescapableResult
326+
@_alwaysEmitIntoClient
327+
@_transparent
328+
@lifetime(borrow source)
329+
internal func _overrideLifetime<
330+
T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable
331+
>(
332+
_ dependent: consuming T,
333+
mutating source: inout U
334+
) -> T {
335+
// TODO: Remove @_unsafeNonescapableResult. Instead, the unsafe dependence
336+
// should be expressed by a builtin that is hidden within the function body.
337+
dependent
338+
}

0 commit comments

Comments
 (0)