Skip to content

Commit c21de06

Browse files
authored
Merge pull request #78561 from glessard/rdar137710901-span-properties-prototype
[SE-0456] Span properties (part 1)
2 parents 498d7cc + 7b03593 commit c21de06

21 files changed

+483
-38
lines changed

Runtimes/Core/cmake/modules/ExperimentalFeatures.cmake

+1-2
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,4 @@ add_compile_options(
1010
"$<$<COMPILE_LANGUAGE:Swift>:SHELL:-enable-experimental-feature FreestandingMacros>"
1111
"$<$<COMPILE_LANGUAGE:Swift>:SHELL:-enable-experimental-feature BitwiseCopyable>"
1212
"$<$<COMPILE_LANGUAGE:Swift>:SHELL:-enable-experimental-feature Extern>"
13-
"$<$<COMPILE_LANGUAGE:Swift>:SHELL:-enable-experimental-feature ValueGenerics>"
14-
"$<$<COMPILE_LANGUAGE:Swift>:SHELL:-enable-experimental-feature AddressableParameters>")
13+
"$<$<COMPILE_LANGUAGE:Swift>:SHELL:-enable-experimental-feature ValueGenerics>")

Runtimes/Core/core/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,8 @@ target_compile_options(swiftCore PRIVATE
279279
# STAGING: Temporarily avoids having to write #fileID in Swift.swiftinterface.
280280
# see also 327ea8bce2d1107a847d444651b19ca6a2901c9e
281281
"$<$<COMPILE_LANGUAGE:Swift>:SHELL:-Xfrontend -enable-experimental-concise-pound-file>"
282+
"$<$<COMPILE_LANGUAGE:Swift>:SHELL:-enable-experimental-feature AddressableParameters>"
283+
"$<$<COMPILE_LANGUAGE:Swift>:SHELL:-enable-experimental-feature AddressableTypes>"
282284
$<$<COMPILE_LANGUAGE:Swift>:-parse-stdlib>
283285
$<$<COMPILE_LANGUAGE:Swift>:-nostdimport>
284286
$<$<COMPILE_LANGUAGE:Swift>:-explicit-module-build>

stdlib/public/core/Array.swift

+20-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2025 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -1427,6 +1427,25 @@ extension Array: RangeReplaceableCollection {
14271427
return try unsafe body(bufferPointer)
14281428
}
14291429
}
1430+
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+
}
14301449

14311450
@inlinable
14321451
public __consuming func _copyToContiguousArray() -> ContiguousArray<Element> {

stdlib/public/core/ArrayBuffer.swift

+15-12
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2025 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -608,11 +608,10 @@ extension _ArrayBuffer {
608608
1 //OBJC_ASSOCIATION_RETAIN_NONATOMIC
609609
)
610610
}
611-
612-
@_alwaysEmitIntoClient @inline(never)
613-
internal func withUnsafeBufferPointer_nonNative<R, E>(
614-
_ body: (UnsafeBufferPointer<Element>) throws(E) -> R
615-
) throws(E) -> R {
611+
612+
@_alwaysEmitIntoClient
613+
internal func getOrAllocateAssociatedObjectBuffer(
614+
) -> _ContiguousArrayBuffer<Element> {
616615
let unwrapped: _ContiguousArrayBuffer<Element>
617616
// libobjc already provides the necessary memory barriers for
618617
// double checked locking to be safe, per comments on
@@ -633,12 +632,16 @@ extension _ArrayBuffer {
633632
defer { _fixLifetime(unwrapped) }
634633
objc_sync_exit(lock)
635634
}
636-
return try unsafe body(
637-
UnsafeBufferPointer(
638-
start: unwrapped.firstElementAddress,
639-
count: unwrapped.count
640-
)
641-
)
635+
return unwrapped
636+
}
637+
638+
@_alwaysEmitIntoClient @inline(never)
639+
internal func withUnsafeBufferPointer_nonNative<R, E>(
640+
_ body: (UnsafeBufferPointer<Element>) throws(E) -> R
641+
) throws(E) -> R {
642+
let buffer = getOrAllocateAssociatedObjectBuffer()
643+
let (pointer, count) = unsafe (buffer.firstElementAddress, buffer.count)
644+
return try unsafe body(UnsafeBufferPointer(start: pointer, count: count))
642645
}
643646

644647
/// Call `body(p)`, where `p` is an `UnsafeBufferPointer` over the

stdlib/public/core/ArraySlice.swift

+12-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2025 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -1116,6 +1116,17 @@ 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+
11191130
@inlinable
11201131
public __consuming func _copyToContiguousArray() -> ContiguousArray<Element> {
11211132
if let n = _buffer.requestNativeBuffer() {

stdlib/public/core/CollectionOfOne.swift

+17-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2025 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -22,6 +22,7 @@
2222
/// let b = a + CollectionOfOne(toAdd)
2323
/// // b == [1, 2, 3, 4, 100]
2424
@frozen // trivial-implementation
25+
@_addressableForDependencies
2526
public struct CollectionOfOne<Element> {
2627
@usableFromInline // trivial-implementation
2728
internal var _element: Element
@@ -158,6 +159,21 @@ extension CollectionOfOne: RandomAccessCollection, MutableCollection {
158159
}
159160
}
160161

162+
extension CollectionOfOne {
163+
164+
@available(SwiftStdlib 6.2, *)
165+
public var span: Span<Element> {
166+
@lifetime(borrow self)
167+
@_alwaysEmitIntoClient
168+
get {
169+
let pointer = unsafe UnsafePointer<Element>(Builtin.addressOfBorrow(self))
170+
let span = unsafe Span(_unsafeStart: pointer, count: 1)
171+
fatalError("Span over CollectionOfOne is not supported yet.")
172+
return unsafe _overrideLifetime(span, borrowing: self)
173+
}
174+
}
175+
}
176+
161177
@_unavailableInEmbedded
162178
extension CollectionOfOne: CustomDebugStringConvertible {
163179
/// A textual representation of the collection, suitable for debugging.

stdlib/public/core/ContiguousArray.swift

+12-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2025 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -1021,6 +1021,17 @@ 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+
10241035
@inlinable
10251036
public __consuming func _copyToContiguousArray() -> ContiguousArray<Element> {
10261037
if let n = _buffer.requestNativeBuffer() {

stdlib/public/core/InlineArray.swift

+21
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
@available(SwiftStdlib 6.2, *)
4444
@frozen
4545
@safe
46+
@_addressableForDependencies
4647
public struct InlineArray<let count: Int, Element: ~Copyable>: ~Copyable {
4748
@usableFromInline
4849
internal let _storage: Builtin.FixedArray<count, Element>
@@ -455,6 +456,26 @@ extension InlineArray where Element: ~Copyable {
455456
}
456457
}
457458

459+
//===----------------------------------------------------------------------===//
460+
// MARK: Span
461+
//===----------------------------------------------------------------------===//
462+
463+
@available(SwiftStdlib 6.2, *)
464+
extension InlineArray where Element: ~Copyable {
465+
466+
@available(SwiftStdlib 6.2, *)
467+
public var span: Span<Element> {
468+
@lifetime(borrow self)
469+
@_alwaysEmitIntoClient
470+
borrowing get {
471+
let pointer = _address
472+
let span = unsafe Span(_unsafeStart: pointer, count: count)
473+
fatalError("Span over InlineArray is not supported yet.")
474+
return unsafe _overrideLifetime(span, borrowing: self)
475+
}
476+
}
477+
}
478+
458479
//===----------------------------------------------------------------------===//
459480
// MARK: - Unsafe APIs
460481
//===----------------------------------------------------------------------===//

stdlib/public/core/KeyValuePairs.swift

+18-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2025 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -125,6 +125,23 @@ extension KeyValuePairs: RandomAccessCollection {
125125
}
126126
}
127127

128+
extension KeyValuePairs {
129+
130+
@available(SwiftStdlib 6.2, *)
131+
public var span: Span<Element> {
132+
@lifetime(borrow self)
133+
@_alwaysEmitIntoClient
134+
get {
135+
let rp = unsafe UnsafeRawPointer(_elements._buffer.firstElementAddress)
136+
let span = unsafe Span(
137+
_unsafeStart: unsafe rp.assumingMemoryBound(to: Element.self),
138+
count: _elements.count
139+
)
140+
return unsafe _overrideLifetime(span, borrowing: self)
141+
}
142+
}
143+
}
144+
128145
@_unavailableInEmbedded
129146
extension KeyValuePairs: CustomStringConvertible {
130147
/// A string that represents the contents of the dictionary.

stdlib/public/core/Span/RawSpan.swift

+10-6
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ public struct RawSpan: ~Escapable, Copyable, BitwiseCopyable {
3232
@usableFromInline
3333
internal let _pointer: UnsafeRawPointer?
3434

35+
@unsafe
3536
@_alwaysEmitIntoClient
3637
internal func _start() -> UnsafeRawPointer {
3738
unsafe _pointer._unsafelyUnwrappedUnchecked
@@ -307,14 +308,17 @@ extension RawSpan {
307308
/// - span: An existing `Span<T>`, which will define both this
308309
/// `RawSpan`'s lifetime and the memory it represents.
309310
@_alwaysEmitIntoClient
310-
@lifetime(borrow span)
311+
@lifetime(copy span)
311312
public init<Element: BitwiseCopyable>(
312-
_elements span: borrowing Span<Element>
313+
_elements span: Span<Element>
313314
) {
314-
unsafe self.init(
315-
_unchecked: span._pointer,
316-
byteCount: span.count &* MemoryLayout<Element>.stride
315+
let pointer = span._pointer
316+
let rawSpan = unsafe RawSpan(
317+
_unchecked: pointer,
318+
byteCount: span.count == 1 ? MemoryLayout<Element>.size
319+
: span.count &* MemoryLayout<Element>.stride
317320
)
321+
self = unsafe _overrideLifetime(rawSpan, copying: span)
318322
}
319323
}
320324

@@ -661,7 +665,7 @@ extension RawSpan {
661665
guard let spanStart = other._pointer, _count > 0 else {
662666
return unsafe _pointer == other._pointer ? 0..<0 : nil
663667
}
664-
let start = _start()
668+
let start = unsafe _start()
665669
let spanEnd = unsafe spanStart + other._count
666670
if unsafe spanStart < start || (start + _count) < spanEnd { return nil }
667671
let lower = unsafe start.distance(to: spanStart)

stdlib/public/core/Span/Span.swift

+15-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ public struct Span<Element: ~Copyable & ~Escapable>
3434
@usableFromInline
3535
internal let _pointer: UnsafeRawPointer?
3636

37+
@unsafe
3738
@_alwaysEmitIntoClient
3839
internal func _start() -> UnsafeRawPointer {
3940
unsafe _pointer._unsafelyUnwrappedUnchecked
@@ -491,6 +492,19 @@ extension Span where Element: BitwiseCopyable {
491492
}
492493
}
493494

495+
@available(SwiftStdlib 6.2, *)
496+
extension Span where Element: BitwiseCopyable {
497+
498+
public var bytes: RawSpan {
499+
@lifetime(copy self)
500+
@_alwaysEmitIntoClient
501+
get {
502+
let rawSpan = RawSpan(_elements: self)
503+
return unsafe _overrideLifetime(rawSpan, copying: self)
504+
}
505+
}
506+
}
507+
494508
// MARK: sub-spans
495509
@available(SwiftStdlib 6.2, *)
496510
extension Span where Element: ~Copyable {
@@ -697,7 +711,7 @@ extension Span where Element: ~Copyable {
697711
guard let spanStart = other._pointer, _count > 0 else {
698712
return unsafe _pointer == other._pointer ? 0..<0 : nil
699713
}
700-
let start = _start()
714+
let start = unsafe _start()
701715
let stride = MemoryLayout<Element>.stride
702716
let spanEnd = unsafe spanStart + stride &* other._count
703717
if unsafe spanStart < start || spanEnd > (start + stride &* _count) {

stdlib/public/core/UnsafeBufferPointer.swift.gyb

+12-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2025 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -564,6 +564,17 @@ extension Unsafe${Mutable}BufferPointer where Element: ~Copyable {
564564
public func extracting(_ bounds: UnboundedRange) -> Self {
565565
unsafe self
566566
}
567+
568+
@unsafe
569+
@available(SwiftStdlib 6.2, *)
570+
public var span: Span<Element> {
571+
@lifetime(borrow self)
572+
@_alwaysEmitIntoClient
573+
get {
574+
let span = unsafe Span(_unsafeElements: self)
575+
return unsafe _overrideLifetime(span, borrowing: self)
576+
}
577+
}
567578
}
568579

569580
extension Unsafe${Mutable}BufferPointer {

stdlib/public/core/UnsafeRawBufferPointer.swift.gyb

+12-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift.org open source project
44
//
5-
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014 - 2025 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See https://swift.org/LICENSE.txt for license information
@@ -1171,6 +1171,17 @@ extension Unsafe${Mutable}RawBufferPointer {
11711171
try unsafe body(${ 'UnsafeBufferPointer<Element>($0)' if Mutable else '$0' })
11721172
}
11731173
}
1174+
1175+
@unsafe
1176+
@available(SwiftStdlib 6.2, *)
1177+
public var bytes: RawSpan {
1178+
@lifetime(borrow self)
1179+
@_alwaysEmitIntoClient
1180+
get {
1181+
let span = unsafe RawSpan(_unsafeBytes: self)
1182+
return unsafe _overrideLifetime(span, borrowing: self)
1183+
}
1184+
}
11741185
}
11751186

11761187
@_unavailableInEmbedded

0 commit comments

Comments
 (0)