diff --git a/Package.swift b/Package.swift index e81fd114..afd07311 100644 --- a/Package.swift +++ b/Package.swift @@ -3,7 +3,7 @@ // // This source file is part of the Swift System open source project // -// Copyright (c) 2020 - 2024 Apple Inc. and the Swift System project authors +// Copyright (c) 2020 - 2026 Apple Inc. and the Swift System project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information @@ -12,63 +12,57 @@ import PackageDescription -struct Available { +struct Availability { var name: String var version: String var osAvailability: String - var sourceAvailability: String - init( - _ version: String, - _ osAvailability: String - ) { - self.name = "System" - self.version = version - self.osAvailability = osAvailability - self.sourceAvailability = "macOS 10.10, iOS 8.0, watchOS 2.0, tvOS 9.0, visionOS 1.0" + var minSwiftPMVersions: String { + "macOS 10.10, iOS 8.0, watchOS 2.0, tvOS 9.0, visionOS 1.0" } - - var swiftSetting: SwiftSetting { - #if SYSTEM_ABI_STABLE - // Use availability matching Darwin API. - let availability = self.osAvailability - #else - // Use availability matching SwiftPM default. - let availability = self.sourceAvailability - #endif - return .enableExperimentalFeature( - "AvailabilityMacro=\(self.name) \(version):\(availability)") + var minSpanDeploymentVersions: String { + "macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1.0" } -} - -let availability: [Available] = [ - Available("0.0.1", "macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0"), - - Available("0.0.2", "macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0"), - Available("0.0.3", "macOS 12.3, iOS 15.4, watchOS 8.5, tvOS 15.4"), - Available("1.1.0", "macOS 12.3, iOS 15.4, watchOS 8.5, tvOS 15.4"), - - Available("1.1.1", "macOS 14.4, iOS 17.4, watchOS 10.4, tvOS 17.4"), - Available("1.2.0", "macOS 14.4, iOS 17.4, watchOS 10.4, tvOS 17.4"), - - Available("1.2.1", "macOS 14.4, iOS 17.4, watchOS 10.4, tvOS 17.4"), - Available("1.3.0", "macOS 14.4, iOS 17.4, watchOS 10.4, tvOS 17.4"), - - Available("1.3.1", "macOS 14.4, iOS 17.4, watchOS 10.4, tvOS 17.4, visionOS 1.0"), - Available("1.3.2", "macOS 14.4, iOS 17.4, watchOS 10.4, tvOS 17.4, visionOS 1.0"), - Available("1.4.0", "macOS 14.4, iOS 17.4, watchOS 10.4, tvOS 17.4, visionOS 1.0"), + var isStandardAvailability: Bool { name == "System" } +} - Available("1.4.1", "macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, visionOS 9999"), - Available("1.4.2", "macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, visionOS 9999"), - Available("1.5.0", "macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, visionOS 9999"), - Available("1.6.0", "macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, visionOS 9999"), - Available("1.6.1", "macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, visionOS 9999"), +let availabilityMap: [(String, String)] = [ + ("0.0.1", "macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0"), + ("0.0.2", "macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0"), + ("1.1.0", "macOS 12.3, iOS 15.4, watchOS 8.5, tvOS 15.4"), + ("1.2.0", "macOS 14.4, iOS 17.4, watchOS 10.4, tvOS 17.4"), + ("1.4.0", "macOS 14.4, iOS 17.4, watchOS 10.4, tvOS 17.4, visionOS 1.0"), - Available("99", "macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, visionOS 9999"), + ("99", "macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, visionOS 9999"), ] -let swiftSettingsAvailability = availability.map(\.swiftSetting) +let availabilities: [Availability] = + availabilityMap.map { + Availability(name: "System", version: $0.0, osAvailability: $0.1) + } + availabilityMap.prefix(5).map { + Availability(name: "SystemWithSpan", version: $0.0, osAvailability: $0.1) + } + +let swiftSettingsAvailability = availabilities.map { + availability -> SwiftSetting in + let osVersionList: String +#if SYSTEM_ABI_STABLE + // Use availability matching Darwin API. + osVersionList = availability.osAvailability +#else + if availability.isStandardAvailability { + // Use availability matching SwiftPM minimum. + osVersionList = availability.minSwiftPMVersions + } else { + // Use availability matching Span deployment minimum. + osVersionList = availability.minSpanDeploymentVersions + } +#endif + return .enableExperimentalFeature( + "AvailabilityMacro=\(availability.name) \(availability.version):\(osVersionList)" + ) +} #if SYSTEM_CI let swiftSettingsCI: [SwiftSetting] = [ diff --git a/Sources/Samples/Connect.swift b/Sources/Samples/Connect.swift index 889da894..86c254cb 100644 --- a/Sources/Samples/Connect.swift +++ b/Sources/Samples/Connect.swift @@ -24,6 +24,7 @@ struct Connect: ParsableCommand { @Option(name: .shortAndLong, help: "Message to send") var message: String = "Hello from swift-system sockets!" + @available(System 99, *) func run() throws { print("Resolving \(host)...") diff --git a/Sources/Samples/Listen.swift b/Sources/Samples/Listen.swift index b1c789bb..c29f5624 100644 --- a/Sources/Samples/Listen.swift +++ b/Sources/Samples/Listen.swift @@ -21,6 +21,7 @@ struct Listen: ParsableCommand { @Option(name: .shortAndLong, help: "Maximum number of connections to accept (0 for unlimited)") var maxConnections: Int = 0 + @available(System 99, *) func run() throws { // Create socket let server = try SocketDescriptor.open(.ipv4, .stream, protocol: .tcp) diff --git a/Sources/Samples/Resolve.swift b/Sources/Samples/Resolve.swift index f118dab8..aa3a6311 100644 --- a/Sources/Samples/Resolve.swift +++ b/Sources/Samples/Resolve.swift @@ -27,6 +27,7 @@ struct Resolve: ParsableCommand { @Flag(name: .long, help: "Show only IPv6 addresses") var ipv6Only: Bool = false + @available(System 99, *) func run() throws { let family: SocketDescriptor.Domain? if ipv4Only { @@ -73,6 +74,7 @@ struct Resolve: ParsableCommand { } } + @available(System 99, *) private func familyName(_ domain: SocketDescriptor.Domain) -> String { switch domain { case .ipv4: return "IPv4" @@ -82,6 +84,7 @@ struct Resolve: ParsableCommand { } } + @available(System 99, *) private func typeName(_ type: SocketDescriptor.ConnectionType) -> String { switch type { case .stream: return "Stream (TCP)" @@ -91,6 +94,7 @@ struct Resolve: ParsableCommand { } } + @available(System 99, *) private func protocolName(_ proto: SocketDescriptor.ProtocolID) -> String { switch proto { case .tcp: return "TCP" diff --git a/Sources/Samples/ReverseResolve.swift b/Sources/Samples/ReverseResolve.swift index f33a6366..7de3cb9a 100644 --- a/Sources/Samples/ReverseResolve.swift +++ b/Sources/Samples/ReverseResolve.swift @@ -10,6 +10,7 @@ import ArgumentParser import SystemSockets +@available(System 99, *) struct ReverseResolve: ParsableCommand { static let configuration = CommandConfiguration( abstract: "Reverse resolve an IP address to a hostname using getnameinfo" diff --git a/Sources/Samples/Util.swift b/Sources/Samples/Util.swift index 048aeef8..ef05a650 100644 --- a/Sources/Samples/Util.swift +++ b/Sources/Samples/Util.swift @@ -36,6 +36,7 @@ internal func complain(_ message: String) { } } +@available(System 99, *) extension SocketAddress.ResolvedAddress { var niceDescription: String { var proto = "" @@ -48,6 +49,7 @@ extension SocketAddress.ResolvedAddress { } } +@available(System 99, *) extension SocketAddress { var niceDescription: String { if let ipv4 = self.ipv4 { return ipv4.description } @@ -57,6 +59,7 @@ extension SocketAddress { } } +@available(System 99, *) extension SocketDescriptor.ConnectionType { var isConnectionless: Bool { self == .datagram || self == .reliablyDeliveredMessage diff --git a/Sources/Samples/main.swift b/Sources/Samples/main.swift index 4aab7828..7166111d 100644 --- a/Sources/Samples/main.swift +++ b/Sources/Samples/main.swift @@ -10,6 +10,8 @@ import ArgumentParser struct SystemSamples: ParsableCommand { + + @available(System 99, *) static var configuration = CommandConfiguration( commandName: "system-samples", abstract: "A collection of little programs exercising some System features.", diff --git a/Sources/System/FileHelpers.swift b/Sources/System/FileHelpers.swift index 4de4ef12..fe4a8edd 100644 --- a/Sources/System/FileHelpers.swift +++ b/Sources/System/FileHelpers.swift @@ -1,7 +1,7 @@ /* This source file is part of the Swift System open source project - Copyright (c) 2020 Apple Inc. and the Swift System project authors + Copyright (c) 2020 - 2026 Apple Inc. and the Swift System project authors Licensed under Apache License v2.0 with Runtime Library Exception See https://swift.org/LICENSE.txt for license information @@ -20,6 +20,7 @@ extension FileDescriptor { /// If `body` throws an error /// or an error occurs while closing the file descriptor, /// this method rethrows that error. + @available(System 0.0.1, *) public func closeAfter(_ body: () throws -> R) throws -> R { // No underscore helper, since the closure's throw isn't necessarily typed. let result: R @@ -49,6 +50,7 @@ extension FileDescriptor { /// If `sequence` doesn't implement /// the method, /// temporary space will be allocated as needed. + @available(System 0.0.1, *) @_alwaysEmitIntoClient @discardableResult public func writeAll( @@ -98,6 +100,7 @@ extension FileDescriptor { /// If `sequence` doesn't implement /// the method, /// temporary space will be allocated as needed. + @available(System 0.0.1, *) @_alwaysEmitIntoClient @discardableResult public func writeAll( @@ -106,6 +109,7 @@ extension FileDescriptor { try _writeAll(toAbsoluteOffset: offset, sequence).get() } + @available(System 0.0.1, *) @usableFromInline internal func _writeAll( toAbsoluteOffset offset: Int64, _ sequence: S @@ -115,6 +119,7 @@ extension FileDescriptor { } } + @available(System 0.0.1, *) @_alwaysEmitIntoClient internal func _writeAllBuffer( toAbsoluteOffset offset: Int64, _ buffer: UnsafeRawBufferPointer @@ -134,6 +139,7 @@ extension FileDescriptor { return .success(buffer.count) } +#if compiler(>=6.2) /// Writes the entire contents of a buffer, retrying on partial writes. /// /// - Parameters: @@ -150,7 +156,7 @@ extension FileDescriptor { /// call the ``seek(offset:from:)`` method. /// /// The corresponding C function is `write`. - @available(macOS 15, iOS 18, watchOS 11, tvOS 18, visionOS 2, *) + @available(SystemWithSpan 0.0.1, *) @_alwaysEmitIntoClient public func writeAll( _ data: RawSpan, @@ -177,7 +183,7 @@ extension FileDescriptor { /// this method leaves the file's existing offset unchanged. /// /// The corresponding C function is `pwrite`. - @available(macOS 15, iOS 18, watchOS 11, tvOS 18, visionOS 2, *) + @available(SystemWithSpan 0.0.1, *) @_alwaysEmitIntoClient public func writeAll( toAbsoluteOffset offset: Int64, @@ -205,7 +211,7 @@ extension FileDescriptor { /// call the ``seek(offset:from:)`` method. /// /// The corresponding C function is `read`. - @available(macOS 15, iOS 18, watchOS 11, tvOS 18, visionOS 2, *) + @available(SystemWithSpan 0.0.1, *) @_alwaysEmitIntoClient @discardableResult public func read( @@ -238,7 +244,7 @@ extension FileDescriptor { /// this method leaves the file's existing offset unchanged. /// /// The corresponding C function is `pread`. - @available(macOS 15, iOS 18, watchOS 11, tvOS 18, visionOS 2, *) + @available(SystemWithSpan 0.0.1, *) @_alwaysEmitIntoClient @discardableResult public func read( @@ -257,4 +263,5 @@ extension FileDescriptor { } return originalCapacity - buffer.freeCapacity } +#endif // swift(>=6.2) } diff --git a/Sources/System/FileOperations.swift b/Sources/System/FileOperations.swift index 539a15f2..643e2bb1 100644 --- a/Sources/System/FileOperations.swift +++ b/Sources/System/FileOperations.swift @@ -1,7 +1,7 @@ /* This source file is part of the Swift System open source project - Copyright (c) 2020 - 2025 Apple Inc. and the Swift System project authors + Copyright (c) 2020 - 2026 Apple Inc. and the Swift System project authors Licensed under Apache License v2.0 with Runtime Library Exception See https://swift.org/LICENSE.txt for license information @@ -23,6 +23,7 @@ extension FileDescriptor { /// - Returns: A file descriptor for the open file /// /// The corresponding C function is `open`. + @available(System 0.0.1, *) @_alwaysEmitIntoClient public static func open( _ path: FilePath, @@ -62,6 +63,7 @@ extension FileDescriptor { /// - Returns: A file descriptor for the open file /// /// The corresponding C function is `open`. + @available(System 0.0.1, *) @_alwaysEmitIntoClient public static func open( _ path: UnsafePointer, @@ -75,6 +77,7 @@ extension FileDescriptor { ).get() } + @available(System 0.0.1, *) @usableFromInline internal static func _open( _ path: UnsafePointer, @@ -148,6 +151,7 @@ extension FileDescriptor { /// the object will be deactivated. /// /// The corresponding C function is `close`. + @available(System 0.0.1, *) @_alwaysEmitIntoClient public func close() throws { try _close().get() } @@ -165,6 +169,7 @@ extension FileDescriptor { /// in bytes from the beginning of the file. /// /// The corresponding C function is `lseek`. + @available(System 0.0.1, *) @_alwaysEmitIntoClient @discardableResult public func seek( @@ -173,6 +178,7 @@ extension FileDescriptor { try _seek(offset: offset, from: whence).get() } + @available(System 0.0.1, *) @usableFromInline internal func _seek( offset: Int64, from whence: FileDescriptor.SeekOrigin @@ -210,6 +216,7 @@ extension FileDescriptor { /// call the ``seek(offset:from:)`` method. /// /// The corresponding C function is `read`. + @available(System 0.0.1, *) @_alwaysEmitIntoClient public func read( into buffer: UnsafeMutableRawBufferPointer, @@ -218,6 +225,7 @@ extension FileDescriptor { try _read(into: buffer, retryOnInterrupt: retryOnInterrupt).get() } + @available(System 0.0.1, *) @usableFromInline internal func _read( into buffer: UnsafeMutableRawBufferPointer, @@ -246,6 +254,7 @@ extension FileDescriptor { /// this method leaves the file's existing offset unchanged. /// /// The corresponding C function is `pread`. + @available(System 0.0.1, *) @_alwaysEmitIntoClient public func read( fromAbsoluteOffset offset: Int64, @@ -259,6 +268,7 @@ extension FileDescriptor { ).get() } + @available(System 0.0.1, *) @usableFromInline internal func _read( fromAbsoluteOffset offset: Int64, @@ -299,6 +309,7 @@ extension FileDescriptor { /// call the ``seek(offset:from:)`` method. /// /// The corresponding C function is `write`. + @available(System 0.0.1, *) @_alwaysEmitIntoClient public func write( _ buffer: UnsafeRawBufferPointer, @@ -307,6 +318,7 @@ extension FileDescriptor { try _write(buffer, retryOnInterrupt: retryOnInterrupt).get() } + @available(System 0.0.1, *) @usableFromInline internal func _write( _ buffer: UnsafeRawBufferPointer, @@ -332,6 +344,7 @@ extension FileDescriptor { /// this method leaves the file's existing offset unchanged. /// /// The corresponding C function is `pwrite`. + @available(System 0.0.1, *) @_alwaysEmitIntoClient public func write( toAbsoluteOffset offset: Int64, @@ -341,6 +354,7 @@ extension FileDescriptor { try _write(toAbsoluteOffset: offset, buffer, retryOnInterrupt: retryOnInterrupt).get() } + @available(System 0.0.1, *) @usableFromInline internal func _write( toAbsoluteOffset offset: Int64, @@ -366,6 +380,7 @@ extension FileDescriptor { retryOnInterrupt: retryOnInterrupt) } +#if compiler(>=6.2) /// Writes the contents of a buffer at the current file offset. /// /// - Parameters: @@ -382,7 +397,7 @@ extension FileDescriptor { /// call the ``seek(offset:from:)`` method. /// /// The corresponding C function is `write`. - @available(macOS 15, iOS 18, watchOS 11, tvOS 18, visionOS 2, *) + @available(SystemWithSpan 0.0.1, *) @_alwaysEmitIntoClient public func write( _ data: RawSpan, @@ -408,7 +423,7 @@ extension FileDescriptor { /// this method leaves the file's existing offset unchanged. /// /// The corresponding C function is `pwrite`. - @available(macOS 15, iOS 18, watchOS 11, tvOS 18, visionOS 2, *) + @available(SystemWithSpan 0.0.1, *) @_alwaysEmitIntoClient public func write( toAbsoluteOffset offset: Int64, @@ -420,7 +435,7 @@ extension FileDescriptor { } } - @available(macOS 15, iOS 18, watchOS 11, tvOS 18, visionOS 2, *) + @available(SystemWithSpan 0.0.1, *) @_alwaysEmitIntoClient internal func _readIntoOutputBuffer( _ buffer: UnsafeMutableRawBufferPointer, @@ -459,7 +474,7 @@ extension FileDescriptor { /// call the ``seek(offset:from:)`` method. /// /// The corresponding C function is `read`. - @available(macOS 15, iOS 18, watchOS 11, tvOS 18, visionOS 2, *) + @available(SystemWithSpan 0.0.1, *) @_alwaysEmitIntoClient public func read( into buffer: inout OutputRawSpan, @@ -485,7 +500,7 @@ extension FileDescriptor { /// this method leaves the file's existing offset unchanged. /// /// The corresponding C function is `pread`. - @available(macOS 15, iOS 18, watchOS 11, tvOS 18, visionOS 2, *) + @available(SystemWithSpan 0.0.1, *) @_alwaysEmitIntoClient public func read( fromAbsoluteOffset offset: Int64, @@ -509,6 +524,7 @@ extension FileDescriptor { fatalError("Unexpected error type") } } +#endif // compiler(>=6.2) } #if !os(WASI) diff --git a/Tests/SystemSocketsTests/AncillaryMessageBufferTests.swift b/Tests/SystemSocketsTests/AncillaryMessageBufferTests.swift index 520a0884..437ce568 100644 --- a/Tests/SystemSocketsTests/AncillaryMessageBufferTests.swift +++ b/Tests/SystemSocketsTests/AncillaryMessageBufferTests.swift @@ -13,6 +13,8 @@ import SystemPackage @Suite("Ancillary Message Buffer") struct AncillaryMessageBufferTests { + + @available(System 99, *) @Test("Append and iterate messages") func testAppend() { // Create a buffer of 100 messages, with varying payload lengths. diff --git a/Tests/SystemSocketsTests/SocketDescriptorTests.swift b/Tests/SystemSocketsTests/SocketDescriptorTests.swift index 18fed427..032c6164 100644 --- a/Tests/SystemSocketsTests/SocketDescriptorTests.swift +++ b/Tests/SystemSocketsTests/SocketDescriptorTests.swift @@ -31,17 +31,20 @@ private struct SocketDescriptorTests { // MARK: - Type Tests + @available(System 99, *) @Test func domainValues() { #expect(SocketDescriptor.Domain.ipv4.rawValue == AF_INET) #expect(SocketDescriptor.Domain.ipv6.rawValue == AF_INET6) #expect(SocketDescriptor.Domain.local.rawValue == AF_UNIX) } + @available(System 99, *) @Test func connectionTypeValues() { #expect(SocketDescriptor.ConnectionType.stream.rawValue == SOCK_STREAM) #expect(SocketDescriptor.ConnectionType.datagram.rawValue == SOCK_DGRAM) } + @available(System 99, *) @Test func protocolValues() { #expect(SocketDescriptor.ProtocolID.tcp.rawValue == CInt(IPPROTO_TCP)) #expect(SocketDescriptor.ProtocolID.udp.rawValue == CInt(IPPROTO_UDP)) @@ -79,6 +82,7 @@ private struct SocketDescriptorTests { // MARK: - Shutdown Tests + @available(System 99, *) @Test func shutdownKindValues() { #expect(SocketDescriptor.ShutdownKind.read.rawValue == SHUT_RD) #expect(SocketDescriptor.ShutdownKind.write.rawValue == SHUT_WR) diff --git a/Tests/SystemTests/SpanFileIOTests.swift b/Tests/SystemTests/SpanFileIOTests.swift index d94a29a2..9b6e7be2 100644 --- a/Tests/SystemTests/SpanFileIOTests.swift +++ b/Tests/SystemTests/SpanFileIOTests.swift @@ -2,13 +2,15 @@ // // This source file is part of the Swift System open source project // -// Copyright (c) 2025 Apple Inc. and the Swift System project authors +// Copyright (c) 2025 - 2026 Apple Inc. and the Swift System project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // //===----------------------------------------------------------------------===// +#if compiler(>=6.2) + import Testing #if SYSTEM_PACKAGE @@ -22,7 +24,7 @@ private struct SpanFileIOTests { // MARK: - Basic Functionality - @available(macOS 15, iOS 18, watchOS 11, tvOS 18, visionOS 2, *) + @available(SystemWithSpan 0.0.1, *) @Test func basicReadWriteOperations() async throws { try withTemporaryFilePath(basename: "basicReadWriteOperations") { path in let fd = try FileDescriptor.open( @@ -95,7 +97,7 @@ private struct SpanFileIOTests { } } - @available(macOS 15, iOS 18, watchOS 11, tvOS 18, visionOS 2, *) + @available(SystemWithSpan 0.0.1, *) @Test func writeOperations() async throws { try withTemporaryFilePath(basename: "writeOperations") { path in let fd = try FileDescriptor.open( @@ -131,7 +133,7 @@ private struct SpanFileIOTests { } } - @available(macOS 15, iOS 18, watchOS 11, tvOS 18, visionOS 2, *) + @available(macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2, visionOS 1, *) @Test func readOperations() async throws { try withTemporaryFilePath(basename: "readOperations") { path in let fd = try FileDescriptor.open( @@ -162,7 +164,7 @@ private struct SpanFileIOTests { } } - @available(macOS 15, iOS 18, watchOS 11, tvOS 18, visionOS 2, *) + @available(SystemWithSpan 0.0.1, *) @Test func absoluteOffsetOperations() async throws { try withTemporaryFilePath(basename: "absoluteOffsetOperations") { path in let fd = try FileDescriptor.open( @@ -198,7 +200,7 @@ private struct SpanFileIOTests { // MARK: - Semantic Behavior - @available(macOS 15, iOS 18, watchOS 11, tvOS 18, visionOS 2, *) + @available(SystemWithSpan 0.0.1, *) @Test func partialReadBehavior() async throws { try withTemporaryFilePath(basename: "partialReadBehavior") { path in let fd = try FileDescriptor.open( @@ -232,7 +234,7 @@ private struct SpanFileIOTests { } } - @available(macOS 15, iOS 18, watchOS 11, tvOS 18, visionOS 2, *) + @available(SystemWithSpan 0.0.1, *) @Test func readFillingBehavior() async throws { try withTemporaryFilePath(basename: "readFillingBehavior") { path in let fd = try FileDescriptor.open( @@ -271,7 +273,7 @@ private struct SpanFileIOTests { // MARK: - Edge Cases - @available(macOS 15, iOS 18, watchOS 11, tvOS 18, visionOS 2, *) + @available(SystemWithSpan 0.0.1, *) @Test func emptyIO() async throws { try withTemporaryFilePath(basename: "emptyIO") { path in let fd = try FileDescriptor.open( @@ -308,7 +310,7 @@ private struct SpanFileIOTests { } } - @available(macOS 15, iOS 18, watchOS 11, tvOS 18, visionOS 2, *) + @available(SystemWithSpan 0.0.1, *) @Test func eofBehavior() async throws { try withTemporaryFilePath(basename: "eofBehavior") { path in let fd = try FileDescriptor.open( @@ -348,7 +350,7 @@ private struct SpanFileIOTests { } } - @available(macOS 15, iOS 18, watchOS 11, tvOS 18, visionOS 2, *) + @available(SystemWithSpan 0.0.1, *) @Test func preInitializedSpan() async throws { try withTemporaryFilePath(basename: "preInitializedSpan") { path in let fd = try FileDescriptor.open( @@ -384,7 +386,7 @@ private struct SpanFileIOTests { } } - @available(macOS 15, iOS 18, watchOS 11, tvOS 18, visionOS 2, *) + @available(SystemWithSpan 0.0.1, *) @Test func errorHandling() throws { // Test 1: Reading from closed FD let fd1 = try FileDescriptor.open(FilePath("/dev/null"), .readOnly) @@ -436,7 +438,7 @@ private struct SpanFileIOTests { // MARK: - Regression/Examples - @available(macOS 15, iOS 18, watchOS 11, tvOS 18, visionOS 2, *) + @available(SystemWithSpan 0.0.1, *) @Test func proposalExample() async throws { // Example from the proposal try withTemporaryFilePath(basename: "proposalExample") { path in @@ -461,3 +463,5 @@ private struct SpanFileIOTests { } } } + +#endif // compiler(>=6.2)