Skip to content

Commit b05a48f

Browse files
Adopt SE-0456 Span and Data accessors (swiftlang#326)
SE-0456 added `Span`-providing properties to standard library types; Foundation also added `Data.bytes` and `Data.span` accordingly. These additions subsume the need for the `Data.bytes` and `Span._bytes` shims. The only caller of `Data.bytes` is `AsyncIO.write(_:to:for:)`, which now binds to Foundation's accessor. The removed accessor also escaped the pointer vended by `withUnsafeBytes(_:)`; Foundation's borrowing accessor avoids this. `DataProtocol.bytes` had no callers and is removed as dead code. The only caller of `Span._bytes` is `run(_:input:output:error:)`, which now uses `input.bytes`. `Buffer.bytes` duplicated the hand-rolled `RawSpan` construction and now delegates to `Array._bytes`, leaving a single implementation. `Array._bytes` remains because `Array.span` does not back-deploy below macOS 26, but Subprocess deploys to macOS 13. This can move to `self.span.bytes` once the deployment floor reaches macOS 26.
1 parent c7d98c7 commit b05a48f

5 files changed

Lines changed: 8 additions & 63 deletions

File tree

Sources/Subprocess/API.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ public func run<
188188
output: output,
189189
error: error
190190
) { execution in
191-
_ = try await execution.standardInputWriter.write(input._bytes)
191+
_ = try await execution.standardInputWriter.write(input.bytes)
192192
try await execution.standardInputWriter.finish()
193193
}
194194
}

Sources/Subprocess/Buffer.swift

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,8 @@ extension SubprocessOutputSequence.Buffer {
6363
}
6464
}
6565

66-
// swift-format-ignore
6766
// Access the storage backing this Buffer
6867
public var bytes: RawSpan {
69-
@_lifetime(borrow self)
70-
borrowing get {
71-
let ptr = self.data.withUnsafeBytes { $0 }
72-
let bytes = RawSpan(_unsafeBytes: ptr)
73-
return _overrideLifetime(of: bytes, to: self)
74-
}
68+
return self.data._bytes
7569
}
7670
}

Sources/Subprocess/Span+Subprocess.swift

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,21 +37,14 @@ public func _overrideLifetime<
3737
dependent
3838
}
3939

40-
extension Span where Element: BitwiseCopyable {
41-
internal var _bytes: RawSpan {
42-
@_lifetime(copy self)
43-
@_alwaysEmitIntoClient
44-
get {
45-
let rawSpan = RawSpan(_elements: self)
46-
return _overrideLifetime(of: rawSpan, copyingFrom: self)
47-
}
48-
}
49-
}
50-
5140
extension Array where Element: BitwiseCopyable {
5241
// swift-format-ignore
5342
// Access the storage backing this Buffer
5443
internal var _bytes: RawSpan {
44+
// `Array.span` (SE-0456) is gated to macOS 26 and does not back-deploy,
45+
// but Subprocess deploys to macOS 13, so hand-roll the `RawSpan`. There
46+
// is no back-deployed `Array.span`. Replace with `self.span.bytes` once
47+
// the deployment floor reaches macOS 26.
5548
@_lifetime(borrow self)
5649
borrowing get {
5750
let ptr = self.withUnsafeBytes { $0 }

Sources/Subprocess/SubprocessFoundation/Span+SubprocessFoundation.swift

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -23,50 +23,6 @@ extension Data {
2323
init(_ s: borrowing RawSpan) {
2424
self = s.withUnsafeBytes { Data($0) }
2525
}
26-
27-
internal var bytes: RawSpan {
28-
// FIXME: For demo purpose only
29-
let ptr = self.withUnsafeBytes { ptr in
30-
return ptr
31-
}
32-
let span = RawSpan(_unsafeBytes: ptr)
33-
return _overrideLifetime(of: span, to: self)
34-
}
35-
}
36-
37-
extension DataProtocol {
38-
var bytes: RawSpan {
39-
_read {
40-
if self.regions.isEmpty {
41-
let empty = UnsafeRawBufferPointer(start: nil, count: 0)
42-
let span = RawSpan(_unsafeBytes: empty)
43-
yield _overrideLifetime(of: span, to: self)
44-
} else if self.regions.count == 1 {
45-
// Easy case: there is only one region in the data
46-
let ptr = self.regions.first!.withUnsafeBytes { ptr in
47-
return ptr
48-
}
49-
let span = RawSpan(_unsafeBytes: ptr)
50-
yield _overrideLifetime(of: span, to: self)
51-
} else {
52-
// This data contains discontiguous chunks. We have to
53-
// copy and make a contiguous chunk
54-
var contiguous: ContiguousArray<UInt8>?
55-
for region in self.regions {
56-
if contiguous != nil {
57-
contiguous?.append(contentsOf: region)
58-
} else {
59-
contiguous = .init(region)
60-
}
61-
}
62-
let ptr = contiguous!.withUnsafeBytes { ptr in
63-
return ptr
64-
}
65-
let span = RawSpan(_unsafeBytes: ptr)
66-
yield _overrideLifetime(of: span, to: self)
67-
}
68-
}
69-
}
7026
}
7127

7228
#endif // SubprocessFoundation

Tests/SubprocessTests/IntegrationTests.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -921,6 +921,8 @@ extension SubprocessIntegrationTests {
921921
let expected: Data = try Data(
922922
contentsOf: URL(filePath: theMysteriousIsland.string)
923923
)
924+
// TODO: Pass `expected.span` directly to `_run()`.
925+
// https://github.com/swiftlang/swift/issues/90259
924926
let ptr = expected.withUnsafeBytes { return $0 }
925927
let span: Span<UInt8> = Span(_unsafeBytes: ptr)
926928
let catResult = try await _run(

0 commit comments

Comments
 (0)