Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SE-0467] MutableSpan #79650

Merged
merged 23 commits into from
Mar 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
30a3eae
[stdlib] add `MutableSpan` and `MutableRawSpan`
glessard Feb 27, 2025
ad8e91b
[test] MutableSpan tests
glessard Feb 27, 2025
1ea02c7
[test] own up to new abi
glessard Feb 27, 2025
2fa2391
[stdlib] remove 2 symbols
glessard Feb 27, 2025
f214ef2
[stdlib] small spelling fixes
glessard Feb 27, 2025
484905b
[stdlib] add extracting() to MutableSpan and MutableRawSpan
glessard Feb 27, 2025
cbbe5df
[stdlib] add unsafe annotations
glessard Mar 1, 2025
b39ee18
[stdlib] tweaks to MutableSpan
glessard Mar 5, 2025
4a78667
[stdlib] tweaks to MutableRawSpan
glessard Mar 5, 2025
e470949
[test] MutableRawSpan tests
glessard Mar 5, 2025
51708d0
[test] add MutableSpan slicing tests
glessard Mar 5, 2025
9553982
[stdlib] use the internal unsafe-unwrap
glessard Mar 5, 2025
5a087d1
[stdlib] annotate unsafe initializers
glessard Mar 6, 2025
90684a8
[stdlib] add missing unsafe annotations
glessard Mar 11, 2025
ecebaa5
[stdlib] move `span` properties of array types
glessard Feb 25, 2025
107b38f
[stdlib] add `mutableSpan` to array types
glessard Mar 11, 2025
0c3f084
[test] Array-family `mutableSpan` properties
glessard Mar 11, 2025
7a160a2
[stdlib] de-underscore the `extracting()` methods
glessard Mar 12, 2025
0805abd
[test] own up to new abi
glessard Mar 12, 2025
51db21a
[build] add files for the new build system
glessard Mar 12, 2025
6a7dbb0
[stdlib] update lifetime annotations for Mutable[Raw]Span
glessard Mar 21, 2025
abf29e7
[stdlib] adjust MutableSpan’s element constraint
glessard Mar 28, 2025
32e1ea1
[test] add required LifetimeDependence feature
glessard Mar 28, 2025
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
2 changes: 2 additions & 0 deletions Runtimes/Core/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ add_library(swiftCore
Sort.swift
Span/Span.swift
Span/RawSpan.swift
Span/MutableSpan.swift
Span/MutableRawSpan.swift
StaticString.swift
StaticPrint.swift
Stride.swift
Expand Down
56 changes: 37 additions & 19 deletions stdlib/public/core/Array.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1428,25 +1428,6 @@ extension Array: RangeReplaceableCollection {
}
}

@available(SwiftStdlib 6.2, *)
public var span: Span<Element> {
@lifetime(borrow self)
@_alwaysEmitIntoClient
borrowing get {
#if _runtime(_ObjC)
if _slowPath(!_buffer._isNative) {
let buffer = _buffer.getOrAllocateAssociatedObjectBuffer()
let (pointer, count) = unsafe (buffer.firstElementAddress, buffer.count)
let span = unsafe Span(_unsafeStart: pointer, count: count)
return unsafe _overrideLifetime(span, borrowing: self)
}
#endif
let (pointer, count) = unsafe (_buffer.firstElementAddress, _buffer.count)
let span = unsafe Span(_unsafeStart: pointer, count: count)
return unsafe _overrideLifetime(span, borrowing: self)
}
}

@inlinable
public __consuming func _copyToContiguousArray() -> ContiguousArray<Element> {
if let n = _buffer.requestNativeBuffer() {
Expand Down Expand Up @@ -1630,6 +1611,27 @@ extension Array {
return try unsafe _buffer.withUnsafeBufferPointer(body)
}

@available(SwiftStdlib 6.2, *)
public var span: Span<Element> {
@lifetime(borrow self)
@_alwaysEmitIntoClient
borrowing get {
#if _runtime(_ObjC)
if _slowPath(!_buffer._isNative) {
let buffer = _buffer.getOrAllocateAssociatedObjectBuffer()
let pointer = unsafe buffer.firstElementAddress
let count = buffer.immutableCount
let span = unsafe Span(_unsafeStart: pointer, count: count)
return unsafe _overrideLifetime(span, borrowing: self)
}
#endif
let pointer = unsafe _buffer.firstElementAddress
let count = _buffer.immutableCount
let span = unsafe Span(_unsafeStart: pointer, count: count)
return unsafe _overrideLifetime(span, borrowing: self)
}
}

// Superseded by the typed-throws version of this function, but retained
// for ABI reasons.
@_semantics("array.withUnsafeMutableBufferPointer")
Expand Down Expand Up @@ -1728,6 +1730,22 @@ extension Array {
return try unsafe body(&inoutBufferPointer)
}

@available(SwiftStdlib 6.2, *)
public var mutableSpan: MutableSpan<Element> {
@lifetime(/*inout*/borrow self)
@_alwaysEmitIntoClient
mutating get {
_makeMutableAndUnique()
// NOTE: We don't have the ability to schedule a call to
// ContiguousArrayBuffer.endCOWMutation().
// rdar://146785284 (lifetime analysis for end of mutation)
let pointer = unsafe _buffer.firstElementAddress
let count = _buffer.mutableCount
let span = unsafe MutableSpan(_unsafeStart: pointer, count: count)
return unsafe _overrideLifetime(span, mutating: &self)
}
}

@inlinable
public __consuming func _copyContents(
initializing buffer: UnsafeMutableBufferPointer<Element>
Expand Down
37 changes: 26 additions & 11 deletions stdlib/public/core/ArraySlice.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1116,17 +1116,6 @@ extension ArraySlice: RangeReplaceableCollection {
}
}

@available(SwiftStdlib 6.2, *)
public var span: Span<Element> {
@lifetime(borrow self)
@_alwaysEmitIntoClient
borrowing get {
let (pointer, count) = (_buffer.firstElementAddress, _buffer.count)
let span = unsafe Span(_unsafeStart: pointer, count: count)
return unsafe _overrideLifetime(span, borrowing: self)
}
}

@inlinable
public __consuming func _copyToContiguousArray() -> ContiguousArray<Element> {
if let n = _buffer.requestNativeBuffer() {
Expand Down Expand Up @@ -1221,6 +1210,17 @@ extension ArraySlice {
return try _buffer.withUnsafeBufferPointer(body)
}

@available(SwiftStdlib 6.2, *)
public var span: Span<Element> {
@lifetime(borrow self)
@_alwaysEmitIntoClient
borrowing get {
let (pointer, count) = unsafe (_buffer.firstElementAddress, _buffer.count)
let span = unsafe Span(_unsafeStart: pointer, count: count)
return unsafe _overrideLifetime(span, borrowing: self)
}
}

// Superseded by the typed-throws version of this function, but retained
// for ABI reasons.
@_semantics("array.withUnsafeMutableBufferPointer")
Expand Down Expand Up @@ -1300,6 +1300,21 @@ extension ArraySlice {
return try unsafe body(&inoutBufferPointer)
}

@available(SwiftStdlib 6.2, *)
public var mutableSpan: MutableSpan<Element> {
@lifetime(/*inout*/borrow self)
@_alwaysEmitIntoClient
mutating get {
_makeMutableAndUnique()
// NOTE: We don't have the ability to schedule a call to
// ContiguousArrayBuffer.endCOWMutation().
// rdar://146785284 (lifetime analysis for end of mutation)
let (pointer, count) = unsafe (_buffer.firstElementAddress, _buffer.count)
let span = unsafe MutableSpan(_unsafeStart: pointer, count: count)
return unsafe _overrideLifetime(span, mutating: &self)
}
}

@inlinable
public __consuming func _copyContents(
initializing buffer: UnsafeMutableBufferPointer<Element>
Expand Down
2 changes: 2 additions & 0 deletions stdlib/public/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ split_embedded_sources(
EMBEDDED Slice.swift
EMBEDDED SmallString.swift
EMBEDDED Sort.swift
EMBEDDED Span/MutableRawSpan.swift
EMBEDDED Span/MutableSpan.swift
EMBEDDED Span/RawSpan.swift
EMBEDDED Span/Span.swift
EMBEDDED StaticString.swift
Expand Down
39 changes: 28 additions & 11 deletions stdlib/public/core/ContiguousArray.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1021,17 +1021,6 @@ extension ContiguousArray: RangeReplaceableCollection {
}
}

@available(SwiftStdlib 6.2, *)
public var span: Span<Element> {
@lifetime(borrow self)
@_alwaysEmitIntoClient
borrowing get {
let (pointer, count) = unsafe (_buffer.firstElementAddress, _buffer.count)
let span = unsafe Span(_unsafeStart: pointer, count: count)
return unsafe _overrideLifetime(span, borrowing: self)
}
}

@inlinable
public __consuming func _copyToContiguousArray() -> ContiguousArray<Element> {
if let n = _buffer.requestNativeBuffer() {
Expand Down Expand Up @@ -1163,6 +1152,18 @@ extension ContiguousArray {
return try unsafe _buffer.withUnsafeBufferPointer(body)
}

@available(SwiftStdlib 6.2, *)
public var span: Span<Element> {
@lifetime(borrow self)
@_alwaysEmitIntoClient
borrowing get {
let pointer = unsafe _buffer.firstElementAddress
let count = _buffer.immutableCount
let span = unsafe Span(_unsafeStart: pointer, count: count)
return unsafe _overrideLifetime(span, borrowing: self)
}
}

// Superseded by the typed-throws version of this function, but retained
// for ABI reasons.
@_semantics("array.withUnsafeMutableBufferPointer")
Expand Down Expand Up @@ -1241,6 +1242,22 @@ extension ContiguousArray {
return try unsafe body(&inoutBufferPointer)
}

@available(SwiftStdlib 6.2, *)
public var mutableSpan: MutableSpan<Element> {
@lifetime(/*inout*/borrow self)
@_alwaysEmitIntoClient
mutating get {
_makeMutableAndUnique()
// NOTE: We don't have the ability to schedule a call to
// ContiguousArrayBuffer.endCOWMutation().
// rdar://146785284 (lifetime analysis for end of mutation)
let pointer = unsafe _buffer.firstElementAddress
let count = _buffer.mutableCount
let span = unsafe MutableSpan(_unsafeStart: pointer, count: count)
return unsafe _overrideLifetime(span, mutating: &self)
}
}

@inlinable
public __consuming func _copyContents(
initializing buffer: UnsafeMutableBufferPointer<Element>
Expand Down
2 changes: 2 additions & 0 deletions stdlib/public/core/GroupInfo.json
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@
"UnsafeRawBufferPointer.swift"
],
"Span": [
"MutableRawSpan.swift",
"MutableSpan.swift",
"RawSpan.swift",
"Span.swift"
],
Expand Down
19 changes: 19 additions & 0 deletions stdlib/public/core/LifetimeManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -297,3 +297,22 @@ internal func _overrideLifetime<
// should be expressed by a builtin that is hidden within the function body.
dependent
}

/// Unsafely discard any lifetime dependency on the `dependent` argument.
/// Return a value identical to `dependent` with a lifetime dependency
/// on the caller's exclusive borrow scope of the `source` argument.
@unsafe
@_unsafeNonescapableResult
@_alwaysEmitIntoClient
@_transparent
@lifetime(borrow source)
internal func _overrideLifetime<
T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable
>(
_ dependent: consuming T,
mutating source: inout U
) -> T {
// TODO: Remove @_unsafeNonescapableResult. Instead, the unsafe dependence
// should be expressed by a builtin that is hidden within the function body.
dependent
}
Loading