From a3aff2f913c26cabbc3bbe40190fb27f9f738cd7 Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Wed, 16 Aug 2023 11:01:36 -0700 Subject: [PATCH 1/3] require Swift 5.6 --- Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index b081a872..5f8efb05 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.2 +// swift-tools-version:5.6 // The swift-tools-version declares the minimum version of Swift required to build this package. /* From f32faad415ee97130b9aa7e6b3a79f5018514931 Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Wed, 16 Aug 2023 11:02:51 -0700 Subject: [PATCH 2/3] remove code depending on Swift older than 5.6 --- .../FilePath/FilePathComponentView.swift | 25 ---- Tests/SystemTests/XCTestManifests.swift | 132 ------------------ 2 files changed, 157 deletions(-) delete mode 100644 Tests/SystemTests/XCTestManifests.swift diff --git a/Sources/System/FilePath/FilePathComponentView.swift b/Sources/System/FilePath/FilePathComponentView.swift index efdd084a..1b9fd21f 100644 --- a/Sources/System/FilePath/FilePathComponentView.swift +++ b/Sources/System/FilePath/FilePathComponentView.swift @@ -39,30 +39,6 @@ extension FilePath { } } - #if SYSTEM_PACKAGE // Workaround for a __consuming getter bug in Swift 5.3.3 - /// View the non-root components that make up this path. - public var components: ComponentView { - get { ComponentView(self) } - _modify { - // RRC's empty init means that we can't guarantee that the yielded - // view will restore our root. So copy it out first. - // - // TODO(perf): Small-form root (especially on Unix). Have Root - // always copy out (not worth ref counting). Make sure that we're - // not needlessly sliding values around or triggering a COW - let rootStr = self.root?._systemString ?? SystemString() - var comp = ComponentView(self) - self = FilePath() - defer { - self = comp._path - if root?._slice.elementsEqual(rootStr) != true { - self.root = Root(rootStr) - } - } - yield &comp - } - } - #else /// View the non-root components that make up this path. public var components: ComponentView { __consuming get { ComponentView(self) } @@ -85,7 +61,6 @@ extension FilePath { yield &comp } } - #endif } @available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) diff --git a/Tests/SystemTests/XCTestManifests.swift b/Tests/SystemTests/XCTestManifests.swift deleted file mode 100644 index de99bd81..00000000 --- a/Tests/SystemTests/XCTestManifests.swift +++ /dev/null @@ -1,132 +0,0 @@ -#if !canImport(ObjectiveC) && swift(<5.5) -import XCTest - -extension ErrnoTest { - // DO NOT MODIFY: This is autogenerated, use: - // `swift test --generate-linuxmain` - // to regenerate. - static let __allTests__ErrnoTest = [ - ("testConstants", testConstants), - ("testPatternMatching", testPatternMatching), - ] -} - -extension FileDescriptorTest { - // DO NOT MODIFY: This is autogenerated, use: - // `swift test --generate-linuxmain` - // to regenerate. - static let __allTests__FileDescriptorTest = [ - ("testConstants", testConstants), - ("testStandardDescriptors", testStandardDescriptors), - ] -} - -extension FileOperationsTest { - // DO NOT MODIFY: This is autogenerated, use: - // `swift test --generate-linuxmain` - // to regenerate. - static let __allTests__FileOperationsTest = [ - ("testAdHocOpen", testAdHocOpen), - ("testAdHocPipe", testAdHocPipe), - ("testGithubIssues", testGithubIssues), - ("testHelpers", testHelpers), - ("testSyscalls", testSyscalls), - ] -} - -extension FilePathComponentsTest { - // DO NOT MODIFY: This is autogenerated, use: - // `swift test --generate-linuxmain` - // to regenerate. - static let __allTests__FilePathComponentsTest = [ - ("testAdHocRRC", testAdHocRRC), - ("testCases", testCases), - ("testSeparatorNormalization", testSeparatorNormalization), - ] -} - -extension FilePathParsingTest { - // DO NOT MODIFY: This is autogenerated, use: - // `swift test --generate-linuxmain` - // to regenerate. - static let __allTests__FilePathParsingTest = [ - ("testNormalization", testNormalization), - ] -} - -extension FilePathSyntaxTest { - // DO NOT MODIFY: This is autogenerated, use: - // `swift test --generate-linuxmain` - // to regenerate. - static let __allTests__FilePathSyntaxTest = [ - ("testAdHocMutations", testAdHocMutations), - ("testFailableStringInitializers", testFailableStringInitializers), - ("testLexicallyRelative", testLexicallyRelative), - ("testPartialWindowsRoots", testPartialWindowsRoots), - ("testPathSyntax", testPathSyntax), - ("testPrefixSuffix", testPrefixSuffix), - ] -} - -extension FilePathTest { - // DO NOT MODIFY: This is autogenerated, use: - // `swift test --generate-linuxmain` - // to regenerate. - static let __allTests__FilePathTest = [ - ("testFilePath", testFilePath), - ] -} - -extension FilePermissionsTest { - // DO NOT MODIFY: This is autogenerated, use: - // `swift test --generate-linuxmain` - // to regenerate. - static let __allTests__FilePermissionsTest = [ - ("testPermissions", testPermissions), - ] -} - -extension MockingTest { - // DO NOT MODIFY: This is autogenerated, use: - // `swift test --generate-linuxmain` - // to regenerate. - static let __allTests__MockingTest = [ - ("testMocking", testMocking), - ] -} - -extension SystemCharTest { - // DO NOT MODIFY: This is autogenerated, use: - // `swift test --generate-linuxmain` - // to regenerate. - static let __allTests__SystemCharTest = [ - ("testIsLetter", testIsLetter), - ] -} - -extension SystemStringTest { - // DO NOT MODIFY: This is autogenerated, use: - // `swift test --generate-linuxmain` - // to regenerate. - static let __allTests__SystemStringTest = [ - ("testAdHoc", testAdHoc), - ("testPlatformString", testPlatformString), - ] -} - -public func __allTests() -> [XCTestCaseEntry] { - return [ - testCase(ErrnoTest.__allTests__ErrnoTest), - testCase(FileDescriptorTest.__allTests__FileDescriptorTest), - testCase(FileOperationsTest.__allTests__FileOperationsTest), - testCase(FilePathComponentsTest.__allTests__FilePathComponentsTest), - testCase(FilePathParsingTest.__allTests__FilePathParsingTest), - testCase(FilePathSyntaxTest.__allTests__FilePathSyntaxTest), - testCase(FilePathTest.__allTests__FilePathTest), - testCase(FilePermissionsTest.__allTests__FilePermissionsTest), - testCase(MockingTest.__allTests__MockingTest), - testCase(SystemCharTest.__allTests__SystemCharTest), - testCase(SystemStringTest.__allTests__SystemStringTest), - ] -} -#endif From 87e68fca36465a17de7176c9e0267a4f5fd91591 Mon Sep 17 00:00:00 2001 From: Guillaume Lessard Date: Wed, 16 Aug 2023 11:19:06 -0700 Subject: [PATCH 3/3] declare `Sendable` conformances along with the types - `Sendable` is fundamental, it is preferably not declared as an extension. --- Sources/System/FileDescriptor.swift | 20 ++++++------------- Sources/System/FilePath/FilePath.swift | 7 +------ .../FilePath/FilePathComponentView.swift | 15 +++++--------- .../System/FilePath/FilePathComponents.swift | 20 ++++++------------- Sources/System/FilePermissions.swift | 7 +------ Sources/System/SystemString.swift | 10 +++------- 6 files changed, 22 insertions(+), 57 deletions(-) diff --git a/Sources/System/FileDescriptor.swift b/Sources/System/FileDescriptor.swift index 556e63ed..eda4f118 100644 --- a/Sources/System/FileDescriptor.swift +++ b/Sources/System/FileDescriptor.swift @@ -45,7 +45,8 @@ extension FileDescriptor { extension FileDescriptor { /// The desired read and write access for a newly opened file. @frozen - public struct AccessMode: RawRepresentable, Hashable, Codable { + @available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) + public struct AccessMode: RawRepresentable, Sendable, Hashable, Codable { /// The raw C access mode. @_alwaysEmitIntoClient public var rawValue: CInt @@ -87,7 +88,8 @@ extension FileDescriptor { /// Options that specify behavior for a newly-opened file. @frozen - public struct OpenOptions: OptionSet, Hashable, Codable { + @available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) + public struct OpenOptions: OptionSet, Sendable, Hashable, Codable { /// The raw C options. @_alwaysEmitIntoClient public var rawValue: CInt @@ -311,7 +313,8 @@ extension FileDescriptor { /// Options for specifying what a file descriptor's offset is relative to. @frozen - public struct SeekOrigin: RawRepresentable, Hashable, Codable { + @available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) + public struct SeekOrigin: RawRepresentable, Sendable, Hashable, Codable { /// The raw C value. @_alwaysEmitIntoClient public var rawValue: CInt @@ -475,18 +478,7 @@ extension FileDescriptor.OpenOptions public var debugDescription: String { self.description } } -#if compiler(>=5.5) && canImport(_Concurrency) // The decision on whether to make FileDescriptor Sendable or not // is currently being discussed in https://github.com/apple/swift-system/pull/112 //@available(*, unavailable, message: "File descriptors are not completely thread-safe.") //extension FileDescriptor: Sendable {} - -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) -extension FileDescriptor.AccessMode: Sendable {} - -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) -extension FileDescriptor.OpenOptions: Sendable {} - -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) -extension FileDescriptor.SeekOrigin: Sendable {} -#endif diff --git a/Sources/System/FilePath/FilePath.swift b/Sources/System/FilePath/FilePath.swift index c1dfd7f3..13064b5a 100644 --- a/Sources/System/FilePath/FilePath.swift +++ b/Sources/System/FilePath/FilePath.swift @@ -38,7 +38,7 @@ /// are file-system–specific and have additional considerations /// like case insensitivity, Unicode normalization, and symbolic links. @available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) -public struct FilePath { +public struct FilePath: Sendable { // TODO(docs): Section on all the new syntactic operations, lexical normalization, decomposition, // components, etc. internal var _storage: SystemString @@ -67,8 +67,3 @@ extension FilePath { @available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) extension FilePath: Hashable, Codable {} - -#if compiler(>=5.5) && canImport(_Concurrency) -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) -extension FilePath: Sendable {} -#endif diff --git a/Sources/System/FilePath/FilePathComponentView.swift b/Sources/System/FilePath/FilePathComponentView.swift index 1b9fd21f..39381b4b 100644 --- a/Sources/System/FilePath/FilePathComponentView.swift +++ b/Sources/System/FilePath/FilePathComponentView.swift @@ -28,7 +28,8 @@ extension FilePath { /// /// path.components.removeAll { $0.kind == .currentDirectory } /// // path is "/home/username/bin/scripts/tree" - public struct ComponentView { + @available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) + public struct ComponentView: Sendable { internal var _path: FilePath internal var _start: SystemString.Index @@ -66,7 +67,9 @@ extension FilePath { @available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) extension FilePath.ComponentView: BidirectionalCollection { public typealias Element = FilePath.Component - public struct Index: Comparable, Hashable { + + @available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) + public struct Index: Sendable, Comparable, Hashable { internal typealias Storage = SystemString.Index internal var _storage: Storage @@ -214,11 +217,3 @@ extension FilePath.ComponentView { #endif // DEBUG } } - -#if compiler(>=5.5) && canImport(_Concurrency) -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) -extension FilePath.ComponentView: Sendable {} - -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) -extension FilePath.ComponentView.Index: Sendable {} -#endif diff --git a/Sources/System/FilePath/FilePathComponents.swift b/Sources/System/FilePath/FilePathComponents.swift index ecd713ea..6b8a9408 100644 --- a/Sources/System/FilePath/FilePathComponents.swift +++ b/Sources/System/FilePath/FilePathComponents.swift @@ -28,7 +28,8 @@ extension FilePath { /// * `\\server\share\` /// * `\\?\UNC\server\share\` /// * `\\?\Volume{12345678-abcd-1111-2222-123445789abc}\` - public struct Root { + @available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) + public struct Root: Sendable { internal var _path: FilePath internal var _rootEnd: SystemString.Index @@ -54,7 +55,8 @@ extension FilePath { /// file.kind == .regular // true /// file.extension // "txt" /// path.append(file) // path is "/tmp/foo.txt" - public struct Component { + @available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) + public struct Component: Sendable { internal var _path: FilePath internal var _range: Range @@ -78,7 +80,8 @@ extension FilePath.Component { /// Whether a component is a regular file or directory name, or a special /// directory `.` or `..` @frozen - public enum Kind { + @available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) + public enum Kind: Sendable { /// The special directory `.`, representing the current directory. case currentDirectory @@ -285,14 +288,3 @@ extension FilePath.Root { #endif } } - -#if compiler(>=5.5) && canImport(_Concurrency) -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) -extension FilePath.Root: Sendable {} - -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) -extension FilePath.Component: Sendable {} - -@available(/*System 0.0.2: macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0*/iOS 8, *) -extension FilePath.Component.Kind: Sendable {} -#endif diff --git a/Sources/System/FilePermissions.swift b/Sources/System/FilePermissions.swift index 9bd6c5fb..2cdb32ff 100644 --- a/Sources/System/FilePermissions.swift +++ b/Sources/System/FilePermissions.swift @@ -18,7 +18,7 @@ /// perms == [.ownerReadWrite, .groupRead, .otherRead] // true @frozen @available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) -public struct FilePermissions: OptionSet, Hashable, Codable { +public struct FilePermissions: OptionSet, Sendable, Hashable, Codable { /// The raw C file permissions. @_alwaysEmitIntoClient public let rawValue: CModeT @@ -175,8 +175,3 @@ extension FilePermissions /// A textual representation of the file permissions, suitable for debugging. public var debugDescription: String { self.description } } - -#if compiler(>=5.5) && canImport(_Concurrency) -@available(/*System 0.0.1: macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0*/iOS 8, *) -extension FilePermissions: Sendable {} -#endif diff --git a/Sources/System/SystemString.swift b/Sources/System/SystemString.swift index 14651d52..9bfef49f 100644 --- a/Sources/System/SystemString.swift +++ b/Sources/System/SystemString.swift @@ -8,7 +8,8 @@ */ // A platform-native character representation, currently used for file paths -internal struct SystemChar: RawRepresentable, Comparable, Hashable, Codable { +internal struct SystemChar: + RawRepresentable, Sendable, Comparable, Hashable, Codable { internal typealias RawValue = CInterop.PlatformChar internal var rawValue: RawValue @@ -61,7 +62,7 @@ extension SystemChar { // A platform-native string representation, currently for file paths // // Always null-terminated. -internal struct SystemString { +internal struct SystemString: Sendable { internal typealias Storage = [SystemChar] internal var nullTerminatedStorage: Storage } @@ -288,11 +289,6 @@ extension SystemString { } } -#if compiler(>=5.5) && canImport(_Concurrency) -extension SystemChar: Sendable {} -extension SystemString: Sendable {} -#endif - // TODO: SystemString should use a COW-interchangable storage form rather // than array, so you could "borrow" the storage from a non-bridged String // or Data or whatever