From 2de68a517d504a990cffa67f4fe25803aebdf9e0 Mon Sep 17 00:00:00 2001 From: Islon Scherer Date: Mon, 18 Aug 2025 14:23:08 +0200 Subject: [PATCH 1/5] Add support for Swift 6 --- DEVELOPMENT.adoc | 4 +- Package.swift | 24 ++++++--- .../Decoder/MessagePackDecoder.swift | 2 +- .../SingleValueDecodingContainer.swift | 8 +-- .../SingleValueEncodingContainer.swift | 8 +-- Sources/MessagePack/IO.swift | 10 ++-- Sources/PklSwift/API/DataSize.swift | 4 +- Sources/PklSwift/API/Duration.swift | 4 +- Sources/PklSwift/Decoder/PklDecoder.swift | 2 +- Sources/PklSwift/Evaluator.swift | 10 ++-- Sources/PklSwift/EvaluatorManager.swift | 10 ++-- Sources/PklSwift/EvaluatorOptions.swift | 8 +-- Sources/PklSwift/Logger.swift | 6 +-- Sources/PklSwift/Message.swift | 54 +++++++++---------- Sources/PklSwift/MessageTransport.swift | 11 ++-- Sources/PklSwift/ModuleSource.swift | 2 +- Sources/PklSwift/PklCodingKey.swift | 2 +- Sources/PklSwift/PklEvaluatorSettings.swift | 10 ++-- Sources/PklSwift/Project.swift | 2 +- Sources/PklSwift/Reader.swift | 4 +- Sources/PklSwift/TypeRegistry.swift | 4 +- Sources/PklSwift/Utils.swift | 6 +-- Sources/PklSwift/locks.swift | 10 +--- .../PklSwiftTests/EvaluatorManagerTest.swift | 2 +- Tests/PklSwiftTests/EvaluatorTest.swift | 22 ++++---- .../Fixtures/Generated/AnyType.pkl.swift | 4 +- .../Fixtures/Generated/ApiTypes.pkl.swift | 2 +- .../Fixtures/Generated/Classes.pkl.swift | 4 +- .../Fixtures/Generated/Collections.pkl.swift | 2 +- .../Fixtures/Generated/Collections2.pkl.swift | 2 +- .../Fixtures/Generated/UnionTypes.pkl.swift | 24 ++++----- .../pkl_swift_example_Poly.pkl.swift | 2 +- .../Generated/pkl_swift_lib1.pkl.swift | 2 +- codegen/src/internal/ClassGen.pkl | 2 +- codegen/src/internal/EnumGen.pkl | 4 +- 35 files changed, 142 insertions(+), 135 deletions(-) diff --git a/DEVELOPMENT.adoc b/DEVELOPMENT.adoc index fee7bfd..3081158 100644 --- a/DEVELOPMENT.adoc +++ b/DEVELOPMENT.adoc @@ -28,4 +28,6 @@ make format swiftformat . hawkeye format ----- \ No newline at end of file +---- + +To regenerate all the test fixtures after changes to the codegen run `make generate-fixtures`. diff --git a/Package.swift b/Package.swift index 4b8ed52..e1944c8 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version: 5.10 +// swift-tools-version: 6.0 //===----------------------------------------------------------------------===// // Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved. // @@ -49,16 +49,19 @@ let package = Package( targets: [ .target( name: "PklSwift", - dependencies: ["MessagePack", "PklSwiftInternals", "SemanticVersion"] + dependencies: ["MessagePack", "PklSwiftInternals", "SemanticVersion"], + swiftSettings: [.enableUpcomingFeature("StrictConcurrency")] ), .target( - name: "PklSwiftInternals" + name: "PklSwiftInternals", + swiftSettings: [.enableUpcomingFeature("StrictConcurrency")] ), .target( name: "MessagePack", dependencies: [ .product(name: "SystemPackage", package: "swift-system"), - ] + ], + swiftSettings: [.enableUpcomingFeature("StrictConcurrency")] ), .executableTarget( name: "pkl-gen-swift", @@ -66,11 +69,13 @@ let package = Package( .product(name: "ArgumentParser", package: "swift-argument-parser"), "PklSwift", ], - resources: [.embedInCode("Resources/VERSION.txt")] + resources: [.embedInCode("Resources/VERSION.txt")], + swiftSettings: [.enableUpcomingFeature("StrictConcurrency")] ), .executableTarget( name: "test-external-reader", - dependencies: ["PklSwift"] + dependencies: ["PklSwift"], + swiftSettings: [.enableUpcomingFeature("StrictConcurrency")] ), .testTarget( name: "PklSwiftTests", @@ -87,14 +92,17 @@ let package = Package( "Fixtures/Collections.pkl", "Fixtures/Poly.pkl", "Fixtures/ApiTypes.pkl", - ] + ], + swiftSettings: [.enableUpcomingFeature("StrictConcurrency")] ), .testTarget( name: "MessagePackTests", dependencies: [ "MessagePack", - ] + ], + swiftSettings: [.enableUpcomingFeature("StrictConcurrency")] ), ], + swiftLanguageModes: [.v5, .v6], cxxLanguageStandard: .cxx20 ) diff --git a/Sources/MessagePack/Decoder/MessagePackDecoder.swift b/Sources/MessagePack/Decoder/MessagePackDecoder.swift index 1470c04..68ba304 100644 --- a/Sources/MessagePack/Decoder/MessagePackDecoder.swift +++ b/Sources/MessagePack/Decoder/MessagePackDecoder.swift @@ -417,7 +417,7 @@ public final class MessagePackDecoder { } /// A generic representation of MessagePack values. -public enum MessagePackValue { +public enum MessagePackValue: @unchecked Sendable { case `nil` case bool(Bool) case int(any BinaryInteger) diff --git a/Sources/MessagePack/Decoder/SingleValueDecodingContainer.swift b/Sources/MessagePack/Decoder/SingleValueDecodingContainer.swift index 7257f1d..31bd7a1 100644 --- a/Sources/MessagePack/Decoder/SingleValueDecodingContainer.swift +++ b/Sources/MessagePack/Decoder/SingleValueDecodingContainer.swift @@ -92,7 +92,7 @@ extension _MessagePackDecoder.SingleValueContainer: SingleValueDecodingContainer } } - func decode(_: Date.Type) throws -> Date { + private func decode(_: Date.Type) throws -> Date { switch value { case .timestamp(let value): return value @@ -101,7 +101,7 @@ extension _MessagePackDecoder.SingleValueContainer: SingleValueDecodingContainer } } - func decode(_: Data.Type) throws -> Data { + private func decode(_: Data.Type) throws -> Data { switch value { case .bin(let value): return Data(value) @@ -110,7 +110,7 @@ extension _MessagePackDecoder.SingleValueContainer: SingleValueDecodingContainer } } - func decode(_: [UInt8].Type) throws -> [UInt8] { + private func decode(_: [UInt8].Type) throws -> [UInt8] { // accept either msgpack binary or array switch value { case .bin(let value): @@ -130,7 +130,7 @@ extension _MessagePackDecoder.SingleValueContainer: SingleValueDecodingContainer } } - func decode(_: URL.Type) throws -> URL { + private func decode(_: URL.Type) throws -> URL { switch value { case .string(let value): if let url = URL(string: value) { diff --git a/Sources/MessagePack/Encoder/SingleValueEncodingContainer.swift b/Sources/MessagePack/Encoder/SingleValueEncodingContainer.swift index f6a3b88..74e7a42 100644 --- a/Sources/MessagePack/Encoder/SingleValueEncodingContainer.swift +++ b/Sources/MessagePack/Encoder/SingleValueEncodingContainer.swift @@ -219,7 +219,7 @@ extension _MessagePackEncoder.SingleValueContainer: SingleValueEncodingContainer self.storage.append(contentsOf: value.bytes) } - func encode(_ value: Date) throws { + private func encode(_ value: Date) throws { try checkCanEncode(value: value) defer { self.canEncodeNewValue = false } @@ -246,7 +246,7 @@ extension _MessagePackEncoder.SingleValueContainer: SingleValueEncodingContainer } } - func encode(_ value: Data) throws { + private func encode(_ value: Data) throws { let length = value.count if let uint8 = UInt8(exactly: length) { self.storage.append(0xC4) @@ -269,7 +269,7 @@ extension _MessagePackEncoder.SingleValueContainer: SingleValueEncodingContainer } } - func encode(_ value: [UInt8]) throws { + private func encode(_ value: [UInt8]) throws { let length = value.count if let uint8 = UInt8(exactly: length) { self.storage.append(0xC4) @@ -292,7 +292,7 @@ extension _MessagePackEncoder.SingleValueContainer: SingleValueEncodingContainer } } - func encode(_ value: URL) throws { + private func encode(_ value: URL) throws { try self.encode(value.absoluteString) } diff --git a/Sources/MessagePack/IO.swift b/Sources/MessagePack/IO.swift index d0d4844..585f9b2 100644 --- a/Sources/MessagePack/IO.swift +++ b/Sources/MessagePack/IO.swift @@ -14,7 +14,7 @@ // limitations under the License. //===----------------------------------------------------------------------===// -public protocol Writer { +public protocol Writer: Sendable { /// Write the given bytes into an output somewhere. func write(_ buffer: UnsafeRawBufferPointer) throws @@ -32,7 +32,7 @@ extension Writer { } } -public protocol Reader { +public protocol Reader: Sendable { /// Reads bytes from somewhere, writing them into the given bytearray. func read(into: UnsafeMutableRawBufferPointer) throws -> Int @@ -41,7 +41,7 @@ public protocol Reader { } /// Writes bytes into an internal buffer. -public class BufferWriter: Writer { +public class BufferWriter: Writer, @unchecked Sendable { var bytes: [UInt8] = [] public func write(_ buffer: UnsafeRawBufferPointer) throws { @@ -54,7 +54,7 @@ public class BufferWriter: Writer { } /// Reads bytes from the provided buffer. -public class BufferReader: Reader { +public class BufferReader: Reader, @unchecked Sendable { let bytes: [UInt8] var index: Int @@ -81,7 +81,7 @@ public class BufferReader: Reader { } /// Like [Reader], but also supports a way to peek bytes. -class PeekableReader: Reader { +class PeekableReader: Reader, @unchecked Sendable { var peekedByte: UInt8? let reader: Reader diff --git a/Sources/PklSwift/API/DataSize.swift b/Sources/PklSwift/API/DataSize.swift index edcaff1..16c372e 100644 --- a/Sources/PklSwift/API/DataSize.swift +++ b/Sources/PklSwift/API/DataSize.swift @@ -18,7 +18,7 @@ import Foundation import MessagePack /// DataSize is the Swift representation of Pkl's `pkl.DataSize`. -public struct DataSize: Hashable { +public struct DataSize: Hashable, Sendable { /// The value of this ``DataSize`` in the unit set in ``unit``. let value: Float64 @@ -150,7 +150,7 @@ extension DataSize { } /// The unit of a ``DataSize``. -public enum DataSizeUnit: String, CaseIterable, Decodable { +public enum DataSizeUnit: String, CaseIterable, Decodable, Sendable { /// byte case b diff --git a/Sources/PklSwift/API/Duration.swift b/Sources/PklSwift/API/Duration.swift index 09daca3..ca674f0 100644 --- a/Sources/PklSwift/API/Duration.swift +++ b/Sources/PklSwift/API/Duration.swift @@ -17,7 +17,7 @@ import Foundation /// Duration is the Swift representation of Pkl's `pkl.Duration`. -public struct Duration: Hashable { +public struct Duration: Hashable, Sendable { /// The value of this ``Duration`` in the unit set in ``unit``. public let value: Float64 @@ -137,7 +137,7 @@ extension Duration { } /// A unit (magnitude) of duration. -public enum DurationUnit: String, CaseIterable, Decodable { +public enum DurationUnit: String, CaseIterable, Decodable, Sendable { /// Nanosecond case ns diff --git a/Sources/PklSwift/Decoder/PklDecoder.swift b/Sources/PklSwift/Decoder/PklDecoder.swift index 409478b..b0acf91 100644 --- a/Sources/PklSwift/Decoder/PklDecoder.swift +++ b/Sources/PklSwift/Decoder/PklDecoder.swift @@ -17,7 +17,7 @@ import Foundation import MessagePack -public enum PklValueType: UInt8, Decodable { +public enum PklValueType: UInt8, Decodable, Sendable { case object = 0x1 case map = 0x2 case mapping = 0x3 diff --git a/Sources/PklSwift/Evaluator.swift b/Sources/PklSwift/Evaluator.swift index cb27db0..ace33b0 100644 --- a/Sources/PklSwift/Evaluator.swift +++ b/Sources/PklSwift/Evaluator.swift @@ -22,7 +22,7 @@ import Foundation /// - Parameters: /// - options: The options used to configure the evaluator. /// - action: The action to perform. -public func withEvaluator(options: EvaluatorOptions, _ action: (Evaluator) async throws -> T) async throws -> T { +public func withEvaluator(options: EvaluatorOptions, _ action: (Evaluator) async throws -> T) async throws -> T { try await withEvaluatorManager { manager in let evaluator: Evaluator = try await manager.newEvaluator(options: options) return try await action(evaluator) @@ -32,7 +32,7 @@ public func withEvaluator(options: EvaluatorOptions, _ action: (Evaluator) as /// Like ``withEvaluator(options:_:)``, but with preconfigured evaluator options. /// /// - Parameter action: The action to perform -public func withEvaluator(_ action: (Evaluator) async throws -> T) async throws -> T { +public func withEvaluator(_ action: (Evaluator) async throws -> T) async throws -> T { try await withEvaluator(options: .preconfigured, action) } @@ -42,7 +42,7 @@ public func withEvaluator(_ action: (Evaluator) async throws -> T) async thro /// - projectBaseURI: The base path containing the PklProject file. /// - action: The action to perform. /// - Returns: The result of the action. -public func withProjectEvaluator(projectBaseURI: URL, _ action: (Evaluator) async throws -> T) async throws -> T { +public func withProjectEvaluator(projectBaseURI: URL, _ action: (Evaluator) async throws -> T) async throws -> T { try await withProjectEvaluator(projectBaseURI: projectBaseURI, options: .preconfigured, action) } @@ -57,7 +57,7 @@ public func withProjectEvaluator(projectBaseURI: URL, _ action: (Evaluator) a /// - options: The base options used to configure the evaluator. /// - action: The action to perform. /// - Returns: The result of the action. -public func withProjectEvaluator( +public func withProjectEvaluator( projectBaseURI: URL, options: EvaluatorOptions, _ action: (Evaluator) async throws -> T @@ -69,7 +69,7 @@ public func withProjectEvaluator( } /// The core API for evaluating Pkl modules. -public struct Evaluator { +public struct Evaluator: Sendable { private var manager: EvaluatorManager private let evaluatorID: Int64 private let resourceReaders: [ResourceReader] diff --git a/Sources/PklSwift/EvaluatorManager.swift b/Sources/PklSwift/EvaluatorManager.swift index b440683..e773acb 100644 --- a/Sources/PklSwift/EvaluatorManager.swift +++ b/Sources/PklSwift/EvaluatorManager.swift @@ -30,7 +30,7 @@ let PKL_EXEC_NAME="pkl" /// /// - Parameter action: The action to perform /// - Returns: The result of `action` -public func withEvaluatorManager(_ action: (EvaluatorManager) async throws -> T) async rethrows -> T { +public func withEvaluatorManager(_ action: (EvaluatorManager) async throws -> T) async rethrows -> T { let manager: EvaluatorManager = .init() var closed = false do { @@ -192,7 +192,7 @@ public actor EvaluatorManager { } /// Convenience method for calling ``withEvaluator(_:)`` with preconfigured evaluator options. - public func withEvaluator(_ action: (Evaluator) async throws -> T) async throws -> T { + public func withEvaluator(_ action: (Evaluator) async throws -> T) async throws -> T { try await self.withEvaluator(options: .preconfigured, action) } @@ -203,7 +203,7 @@ public actor EvaluatorManager { /// - Parameters: /// - options: The options used to configure the evaluator. /// - action: The action to run with the evaluator. - public func withEvaluator(options: EvaluatorOptions, _ action: (Evaluator) async throws -> T) async throws -> T { + public func withEvaluator(options: EvaluatorOptions, _ action: (Evaluator) async throws -> T) async throws -> T { let evaluator = try await newEvaluator(options: options) var closed = false do { @@ -220,7 +220,7 @@ public actor EvaluatorManager { } /// Convenience method for constructing a project evaluator with preconfigured base options. - public func withProjectEvaluator(projectBaseURI: URL, _ action: (Evaluator) async throws -> T) async throws -> T { + public func withProjectEvaluator(projectBaseURI: URL, _ action: (Evaluator) async throws -> T) async throws -> T { try await self.withProjectEvaluator(projectBaseURI: projectBaseURI, options: .preconfigured, action) } @@ -235,7 +235,7 @@ public actor EvaluatorManager { /// - projectBaseURI: The project base path that contains the PklProject file. /// - options: The options used to configure the evaluator. /// - action: The action to run with the evaluator. - public func withProjectEvaluator(projectBaseURI: URL, options: EvaluatorOptions, _ action: (Evaluator) async throws -> T) async throws -> T { + public func withProjectEvaluator(projectBaseURI: URL, options: EvaluatorOptions, _ action: (Evaluator) async throws -> T) async throws -> T { let evaluator = try await newProjectEvaluator(projectBaseURI: projectBaseURI, options: options) var closed = false do { diff --git a/Sources/PklSwift/EvaluatorOptions.swift b/Sources/PklSwift/EvaluatorOptions.swift index adc76a5..6dba001 100644 --- a/Sources/PklSwift/EvaluatorOptions.swift +++ b/Sources/PklSwift/EvaluatorOptions.swift @@ -16,7 +16,7 @@ import Foundation -public struct EvaluatorOptions { +public struct EvaluatorOptions: Sendable { public init( allowedModules: [String]? = nil, allowedResources: [String]? = nil, @@ -314,7 +314,7 @@ extension EvaluatorOptions { } } -public enum ProjectDependency { +public enum ProjectDependency: Sendable { case local(ProjectLocalDependency) case remote(ProjectRemoteDependency) } @@ -338,13 +338,13 @@ extension ProjectDependency: Codable { } } -public struct ProjectRemoteDependency: Codable, Hashable { +public struct ProjectRemoteDependency: Codable, Hashable, Sendable { let uri: String let checksums: Checksums? } -public struct ProjectLocalDependency: Codable { +public struct ProjectLocalDependency: Codable, Sendable { let uri: String let projectFileUri: String diff --git a/Sources/PklSwift/Logger.swift b/Sources/PklSwift/Logger.swift index ebfe68c..29abbc3 100644 --- a/Sources/PklSwift/Logger.swift +++ b/Sources/PklSwift/Logger.swift @@ -20,7 +20,7 @@ import MessagePack /// Handler to control logging messages emitted by the Pkl evaluator. /// /// To set a logger, register it on EvaluatorOptions.Logger when building an Evaluator. -public protocol Logger { +public protocol Logger: Sendable { /// Log the message using level TRACE. /// /// - Parameters: @@ -36,7 +36,7 @@ public protocol Logger { func warn(message: String, frameUri: String) } -public struct NoopLogger: Logger { +public struct NoopLogger: Logger, Sendable { public func trace(message: String, frameUri: String) { // no-op } @@ -54,7 +54,7 @@ extension Logger { } /// A logger that writes messages to the provided ``FileHandle``. -public struct FileHandleLogger: Logger { +public struct FileHandleLogger: Logger, Sendable { var fileHandle: FileHandle public init(_ fileHandle: FileHandle) { diff --git a/Sources/PklSwift/Message.swift b/Sources/PklSwift/Message.swift index 60bc9ab..73082d4 100644 --- a/Sources/PklSwift/Message.swift +++ b/Sources/PklSwift/Message.swift @@ -17,7 +17,7 @@ import Foundation import MessagePack -protocol Message: Codable {} +protocol Message: Codable, Sendable {} protocol OneWayMessage: Message {} @@ -45,20 +45,20 @@ protocol ServerResponseMessage: ServerMessage, ResponseMessage {} protocol ServerOneWayMessage: ServerMessage, OneWayMessage {} -struct ModuleReaderSpec: Codable { +struct ModuleReaderSpec: Codable, Sendable { let scheme: String let hasHierarchicalUris: Bool let isLocal: Bool let isGlobbable: Bool } -struct ResourceReaderSpec: Codable { +struct ResourceReaderSpec: Codable, Sendable { let scheme: String let hasHierarchicalUris: Bool let isGlobbable: Bool } -enum MessageType: Int, Codable { +enum MessageType: Int, Codable, Sendable { case CREATE_EVALUATOR_REQUEST = 0x20 case CREATE_EVALUATOR_RESPONSE = 0x21 case CLOSE_EVALUATOR = 0x22 @@ -123,7 +123,7 @@ extension MessageType { } } -struct CreateEvaluatorRequest: ClientRequestMessage { +struct CreateEvaluatorRequest: ClientRequestMessage, Sendable { var requestId: Int64 = 0 var allowedModules: [String]? var allowedResources: [String]? @@ -142,7 +142,7 @@ struct CreateEvaluatorRequest: ClientRequestMessage { var externalResourceReaders: [String: ExternalReader]? } -struct ProjectOrDependency: Codable { +struct ProjectOrDependency: Codable, Sendable { var packageUri: String? var type: String var projectFileUri: String? @@ -150,78 +150,78 @@ struct ProjectOrDependency: Codable { var dependencies: [String: ProjectOrDependency]? } -struct Checksums: Codable, Hashable { +struct Checksums: Codable, Hashable, Sendable { var sha256: String? } -struct CreateEvaluatorResponse: ServerResponseMessage { +struct CreateEvaluatorResponse: ServerResponseMessage, Sendable { let requestId: Int64 let evaluatorId: Int64? let error: String? } -struct ReadResourceRequest: ServerRequestMessage { +struct ReadResourceRequest: ServerRequestMessage, Sendable { var requestId: Int64 let evaluatorId: Int64 let uri: URL } -struct ReadResourceResponse: ClientResponseMessage { +struct ReadResourceResponse: ClientResponseMessage, Sendable { var requestId: Int64 var evaluatorId: Int64 var contents: [UInt8]? var error: String? } -struct ReadModuleRequest: ServerRequestMessage { +struct ReadModuleRequest: ServerRequestMessage, Sendable { var requestId: Int64 let evaluatorId: Int64 let uri: URL } -struct ReadModuleResponse: ClientResponseMessage { +struct ReadModuleResponse: ClientResponseMessage, Sendable { var requestId: Int64 var evaluatorId: Int64 var contents: String? var error: String? } -struct ListResourcesRequest: ServerRequestMessage { +struct ListResourcesRequest: ServerRequestMessage, Sendable { var requestId: Int64 var evaluatorId: Int64 var uri: URL } -struct ListResourcesResponse: ClientResponseMessage { +struct ListResourcesResponse: ClientResponseMessage, Sendable { var requestId: Int64 var evaluatorId: Int64 var pathElements: [PathElementMessage]? var error: String? } -struct PathElementMessage: Codable { +struct PathElementMessage: Codable, Sendable { var name: String var isDirectory: Bool } -struct ListModulesRequest: ServerRequestMessage { +struct ListModulesRequest: ServerRequestMessage, Sendable { var requestId: Int64 var evaluatorId: Int64 var uri: URL } -struct ListModulesResponse: ClientResponseMessage { +struct ListModulesResponse: ClientResponseMessage, Sendable { var requestId: Int64 var evaluatorId: Int64 var pathElements: [PathElementMessage]? var error: String? } -struct CloseEvaluatorRequest: ClientOneWayMessage { +struct CloseEvaluatorRequest: ClientOneWayMessage, Sendable { var evaluatorId: Int64 } -struct EvaluateRequest: ClientRequestMessage { +struct EvaluateRequest: ClientRequestMessage, Sendable { var requestId: Int64 var evaluatorId: Int64 var moduleUri: URL @@ -229,19 +229,19 @@ struct EvaluateRequest: ClientRequestMessage { var expr: String? } -struct EvaluateResponse: ServerResponseMessage { +struct EvaluateResponse: ServerResponseMessage, Sendable { let requestId: Int64 let evaluatorId: Int64 let result: [UInt8]? let error: String? } -enum LogLevel: Int, Codable { +enum LogLevel: Int, Codable, Sendable { case trace = 0 case warn = 1 } -struct LogMessage: ServerOneWayMessage { +struct LogMessage: ServerOneWayMessage, Sendable { let evaluatorId: Int64 let level: LogLevel let message: String @@ -249,24 +249,24 @@ struct LogMessage: ServerOneWayMessage { let frameUri: String } -struct InitializeModuleReaderRequest: ServerRequestMessage { +struct InitializeModuleReaderRequest: ServerRequestMessage, Sendable { var requestId: Int64 let scheme: String } -struct InitializeModuleReaderResponse: ClientResponseMessage { +struct InitializeModuleReaderResponse: ClientResponseMessage, Sendable { var requestId: Int64 var spec: ModuleReaderSpec? } -struct InitializeResourceReaderRequest: ServerRequestMessage { +struct InitializeResourceReaderRequest: ServerRequestMessage, Sendable { var requestId: Int64 let scheme: String } -struct InitializeResourceReaderResponse: ClientResponseMessage { +struct InitializeResourceReaderResponse: ClientResponseMessage, Sendable { var requestId: Int64 var spec: ResourceReaderSpec? } -struct CloseExternalProcess: ServerOneWayMessage {} +struct CloseExternalProcess: ServerOneWayMessage, Sendable {} diff --git a/Sources/PklSwift/MessageTransport.swift b/Sources/PklSwift/MessageTransport.swift index b92d825..1070c98 100644 --- a/Sources/PklSwift/MessageTransport.swift +++ b/Sources/PklSwift/MessageTransport.swift @@ -18,7 +18,7 @@ import Foundation import MessagePack import SemanticVersion -protocol MessageTransport { +protocol MessageTransport: Sendable { /// Send a message to the Pkl server. func send(_ message: ClientMessage) throws @@ -64,7 +64,7 @@ extension FileHandle: Writer { } /// A ``MessageTransport`` base class that implements core message handling logic -public class BaseMessageTransport: MessageTransport { +public class BaseMessageTransport: MessageTransport, @unchecked Sendable { var reader: Reader! var writer: Writer! var encoder: MessagePackEncoder! @@ -122,7 +122,7 @@ public class BaseMessageTransport: MessageTransport { } /// A ``MessageTransport`` that sends and receives messages by spawning Pkl as a child process. -public class ServerMessageTransport: BaseMessageTransport { +public class ServerMessageTransport: BaseMessageTransport, @unchecked Sendable { var process: Process? let pklCommand: [String]? @@ -150,7 +150,8 @@ public class ServerMessageTransport: BaseMessageTransport { self.decoder = .init(reader: self.reader) self.process!.standardOutput = self.reader self.process!.standardInput = self.writer - debug("Spawning command \(pklCommand[0]) with arguments \(arguments)") + let debugArguments = arguments + debug("Spawning command \(pklCommand[0]) with arguments \(debugArguments)") try self.process!.run() } @@ -194,7 +195,7 @@ public class ServerMessageTransport: BaseMessageTransport { } } -public class ExternalReaderMessageTransport: BaseMessageTransport { +public class ExternalReaderMessageTransport: BaseMessageTransport, @unchecked Sendable { override var running: Bool { self._running } private var _running = true diff --git a/Sources/PklSwift/ModuleSource.swift b/Sources/PklSwift/ModuleSource.swift index 500b60a..57e63bb 100644 --- a/Sources/PklSwift/ModuleSource.swift +++ b/Sources/PklSwift/ModuleSource.swift @@ -17,7 +17,7 @@ import Foundation /// A representation of a source for a Pkl module to be evaluated. -public struct ModuleSource: Hashable { +public struct ModuleSource: Hashable, Sendable { /// The URI of the module. let uri: URL diff --git a/Sources/PklSwift/PklCodingKey.swift b/Sources/PklSwift/PklCodingKey.swift index 5fa368e..3482d7f 100644 --- a/Sources/PklSwift/PklCodingKey.swift +++ b/Sources/PklSwift/PklCodingKey.swift @@ -16,7 +16,7 @@ import Foundation -public struct PklCodingKey: CodingKey, Equatable { +public struct PklCodingKey: CodingKey, Equatable, Sendable { public let stringValue: String public let intValue: Int? diff --git a/Sources/PklSwift/PklEvaluatorSettings.swift b/Sources/PklSwift/PklEvaluatorSettings.swift index 784153c..2c166ec 100644 --- a/Sources/PklSwift/PklEvaluatorSettings.swift +++ b/Sources/PklSwift/PklEvaluatorSettings.swift @@ -15,7 +15,7 @@ //===----------------------------------------------------------------------===// /// The Swift representation of standard library module `pkl.EvaluatorSettings`. -public struct PklEvaluatorSettings: Decodable, Hashable { +public struct PklEvaluatorSettings: Decodable, Hashable, Sendable { let externalProperties: [String: String]? let env: [String: String]? let allowedModules: [String]? @@ -39,7 +39,7 @@ public struct PklEvaluatorSettings: Decodable, Hashable { let color: PklEvaluatorSettingsColor? } -public enum PklEvaluatorSettingsColor: String, CaseIterable, Decodable, Hashable { +public enum PklEvaluatorSettingsColor: String, CaseIterable, Decodable, Hashable, Sendable { /// Never format. case never @@ -51,7 +51,7 @@ public enum PklEvaluatorSettingsColor: String, CaseIterable, Decodable, Hashable } /// Settings that control how Pkl talks to HTTP(S) servers. -public struct Http: Codable, Hashable { +public struct Http: Codable, Hashable, Sendable { /// PEM format certificates to trust when making HTTP requests. /// /// If empty, Pkl will trust its own built-in certificates. @@ -82,7 +82,7 @@ public struct Http: Codable, Hashable { } /// Settings that control how Pkl talks to HTTP proxies. -public struct Proxy: Codable, Hashable { +public struct Proxy: Codable, Hashable, Sendable { /// The proxy to use for HTTP(S) connections. /// /// Only HTTP proxies are supported. @@ -125,7 +125,7 @@ public struct Proxy: Codable, Hashable { var noProxy: [String]? } -public struct ExternalReader: Codable, Hashable { +public struct ExternalReader: Codable, Hashable, Sendable { var executable: String var arguments: [String]? = nil } diff --git a/Sources/PklSwift/Project.swift b/Sources/PklSwift/Project.swift index c80a755..1ac4a11 100644 --- a/Sources/PklSwift/Project.swift +++ b/Sources/PklSwift/Project.swift @@ -44,7 +44,7 @@ public struct Project: PklRegisteredType, Hashable, DependencyDeclaredInProjectF } } -public protocol DependencyDeclaredInProjectFile: Hashable, Decodable, Equatable {} +public protocol DependencyDeclaredInProjectFile: Hashable, Decodable, Equatable, Sendable {} extension Project: Decodable { public init(from decoder: Decoder) throws { diff --git a/Sources/PklSwift/Reader.swift b/Sources/PklSwift/Reader.swift index 1cd6bf0..4ec1063 100644 --- a/Sources/PklSwift/Reader.swift +++ b/Sources/PklSwift/Reader.swift @@ -16,7 +16,7 @@ import Foundation -public protocol BaseReader { +public protocol BaseReader: Sendable { /// The scheme part of the URL that this reader can read. var scheme: String { get } @@ -101,7 +101,7 @@ extension ResourceReader { /// /// For example, a ``PathElement`` with name `bar.txt` and is not a directory at base URI `file:////foo/` /// implies URI resource `file:///foo/bar.txt`. -public struct PathElement { +public struct PathElement: Sendable { /// The name of the path element public let name: String diff --git a/Sources/PklSwift/TypeRegistry.swift b/Sources/PklSwift/TypeRegistry.swift index e0133b7..e48ade2 100644 --- a/Sources/PklSwift/TypeRegistry.swift +++ b/Sources/PklSwift/TypeRegistry.swift @@ -20,7 +20,7 @@ import PklSwiftInternals /// Marker protocol that all generated Pkl types should conform to. /// /// It is used by the TypeRegistry to find the types at runtime, and dynamically form a registry of all known pkl types. -public protocol PklRegisteredType: Decodable { +public protocol PklRegisteredType: Decodable, Sendable { static var registeredIdentifier: String { get } } @@ -107,7 +107,7 @@ extension TypeRegistry { extension TypeRegistry { static let _sharedLock: PklLock = .init() - static var _shared: TypeRegistry? + nonisolated(unsafe) static var _shared: TypeRegistry? public static func get() -> TypeRegistry { self._sharedLock.withLock { diff --git a/Sources/PklSwift/Utils.swift b/Sources/PklSwift/Utils.swift index 7e7c7cd..97b3b38 100644 --- a/Sources/PklSwift/Utils.swift +++ b/Sources/PklSwift/Utils.swift @@ -18,7 +18,7 @@ import Foundation let pklDebug = ProcessInfo.processInfo.environment["PKL_DEBUG"] == "1" -func debug(_ message: @autoclosure () -> String) { +func debug(_ message: @autoclosure @Sendable () -> String) { if !pklDebug { return } @@ -33,7 +33,7 @@ let longNumberFormatter: NumberFormatter = { return ret }() -func format(fractional: some BinaryFloatingPoint) -> String? { +@Sendable func format(fractional: some BinaryFloatingPoint) -> String? { longNumberFormatter.string(from: NSNumber(value: Float64(fractional))) } @@ -84,7 +84,7 @@ public func resolvePaths(_ paths: String...) -> String { return result } -public let absoluteUriRegex = try! Regex("\\w+:") +public nonisolated(unsafe) let absoluteUriRegex = try! Regex("\\w+:") public func tempDir() throws -> URL { try (FileManager.default.url(for: .itemReplacementDirectory, in: .userDomainMask, appropriateFor: URL(fileURLWithPath: "/"), create: true)) diff --git a/Sources/PklSwift/locks.swift b/Sources/PklSwift/locks.swift index 1f52a01..c551744 100644 --- a/Sources/PklSwift/locks.swift +++ b/Sources/PklSwift/locks.swift @@ -197,8 +197,6 @@ final class LockStorage: ManagedBuffer { } } -extension LockStorage: @unchecked Sendable {} - /// A threading lock based on `libpthread` instead of `libdispatch`. /// /// - note: ``PklLock`` has reference semantics. @@ -207,7 +205,7 @@ extension LockStorage: @unchecked Sendable {} /// of lock is safe to use with `libpthread`-based threading models, such as the /// one used by Pkl. On Windows, the lock is based on the substantially similar /// `SRWLOCK` type. -public struct PklLock { +public struct PklLock: @unchecked Sendable { @usableFromInline let _storage: LockStorage @@ -265,8 +263,6 @@ extension PklLock { } } -extension PklLock: Sendable {} - extension UnsafeMutablePointer { @inlinable func assertValidAlignment() { @@ -274,7 +270,7 @@ extension UnsafeMutablePointer { } } -public struct PklLockedValueBox { +public struct PklLockedValueBox: @unchecked Sendable { @usableFromInline let _storage: LockStorage @@ -290,5 +286,3 @@ public struct PklLockedValueBox { try self._storage.withLockedValue(mutate) } } - -extension PklLockedValueBox: Sendable where Value: Sendable {} diff --git a/Tests/PklSwiftTests/EvaluatorManagerTest.swift b/Tests/PklSwiftTests/EvaluatorManagerTest.swift index 3c76b81..af8f75a 100644 --- a/Tests/PklSwiftTests/EvaluatorManagerTest.swift +++ b/Tests/PklSwiftTests/EvaluatorManagerTest.swift @@ -19,7 +19,7 @@ import XCTest @testable import PklSwift -class FakeMessageTransport: MessageTransport { +class FakeMessageTransport: MessageTransport, @unchecked Sendable { var outboundStream: AsyncThrowingStream! var outboundContinuation: AsyncThrowingStream.Continuation! diff --git a/Tests/PklSwiftTests/EvaluatorTest.swift b/Tests/PklSwiftTests/EvaluatorTest.swift index bff003d..a8bc61b 100644 --- a/Tests/PklSwiftTests/EvaluatorTest.swift +++ b/Tests/PklSwiftTests/EvaluatorTest.swift @@ -20,7 +20,7 @@ import Foundation import SemanticVersion import XCTest -class TestLogger: Logger { +class TestLogger: Logger, @unchecked Sendable { var logLines: [String] = [] func trace(message: String, frameUri: String) { @@ -32,7 +32,7 @@ class TestLogger: Logger { } } -struct VirtualModuleReader: ModuleReader { +struct VirtualModuleReader: ModuleReader, @unchecked Sendable { func read(url: URL) async throws -> String { try await self.read(url) } @@ -41,9 +41,9 @@ struct VirtualModuleReader: ModuleReader { try await self.listElements(uri) } - var read: (URL) async throws -> String + var read: @Sendable (URL) async throws -> String - var listElements: (URL) async throws -> [PathElement] + var listElements: @Sendable (URL) async throws -> [PathElement] var scheme: String @@ -54,16 +54,16 @@ struct VirtualModuleReader: ModuleReader { var isLocal: Bool } -struct VirtualResourceReader: ResourceReader { +struct VirtualResourceReader: ResourceReader, @unchecked Sendable { var scheme: String var isGlobbable: Bool var hasHierarchicalUris: Bool - var read: (URL) async throws -> [UInt8] + var read: @Sendable (URL) async throws -> [UInt8] - var listElements: (URL) async throws -> [PathElement] + var listElements: @Sendable (URL) async throws -> [PathElement] func read(url: URL) async throws -> [UInt8] { try await self.read(url) @@ -307,18 +307,20 @@ final class PklSwiftTests: XCTestCase { } func testConcurrenctEvaluations() async throws { + // not safe to capture `self` in a task, so making a copy + let manager = self.manager! async let evalResult1 = try Task { - let evaluator = try await self.manager.newEvaluator(options: .preconfigured) + let evaluator = try await manager.newEvaluator(options: .preconfigured) return try await evaluator.evaluateOutputText(source: .text("foo = 1")) }.result.get() async let evalResult2 = try Task { - let evaluator = try await self.manager.newEvaluator(options: .preconfigured) + let evaluator = try await manager.newEvaluator(options: .preconfigured) return try await evaluator.evaluateOutputText(source: .text("foo = 2")) }.result.get() async let evalResult3 = try Task { - let evaluator = try await self.manager.newEvaluator(options: .preconfigured) + let evaluator = try await manager.newEvaluator(options: .preconfigured) return try await evaluator.evaluateOutputText(source: .text("foo = 3")) }.result.get() diff --git a/Tests/PklSwiftTests/Fixtures/Generated/AnyType.pkl.swift b/Tests/PklSwiftTests/Fixtures/Generated/AnyType.pkl.swift index f038a1b..a5a92b9 100644 --- a/Tests/PklSwiftTests/Fixtures/Generated/AnyType.pkl.swift +++ b/Tests/PklSwiftTests/Fixtures/Generated/AnyType.pkl.swift @@ -4,7 +4,7 @@ import PklSwift public enum AnyType {} extension AnyType { - public struct Module: PklRegisteredType, Decodable, Hashable { + public struct Module: PklRegisteredType, Decodable, Hashable, @unchecked Sendable { public static let registeredIdentifier: String = "AnyType" public var bird: AnyHashable? @@ -62,7 +62,7 @@ extension AnyType { } } - public struct Bird: PklRegisteredType, Decodable, Hashable { + public struct Bird: PklRegisteredType, Decodable, Hashable, @unchecked Sendable { public static let registeredIdentifier: String = "AnyType#Bird" public var species: String diff --git a/Tests/PklSwiftTests/Fixtures/Generated/ApiTypes.pkl.swift b/Tests/PklSwiftTests/Fixtures/Generated/ApiTypes.pkl.swift index d19ddb5..4c026ca 100644 --- a/Tests/PklSwiftTests/Fixtures/Generated/ApiTypes.pkl.swift +++ b/Tests/PklSwiftTests/Fixtures/Generated/ApiTypes.pkl.swift @@ -4,7 +4,7 @@ import PklSwift public enum ApiTypes {} extension ApiTypes { - public struct Module: PklRegisteredType, Decodable, Hashable { + public struct Module: PklRegisteredType, Decodable, Hashable, @unchecked Sendable { public static let registeredIdentifier: String = "ApiTypes" public var res1: Duration diff --git a/Tests/PklSwiftTests/Fixtures/Generated/Classes.pkl.swift b/Tests/PklSwiftTests/Fixtures/Generated/Classes.pkl.swift index 9cf62f0..0e2e422 100644 --- a/Tests/PklSwiftTests/Fixtures/Generated/Classes.pkl.swift +++ b/Tests/PklSwiftTests/Fixtures/Generated/Classes.pkl.swift @@ -4,7 +4,7 @@ import PklSwift public enum Classes {} extension Classes { - public struct Module: PklRegisteredType, Decodable, Hashable { + public struct Module: PklRegisteredType, Decodable, Hashable, @unchecked Sendable { public static let registeredIdentifier: String = "Classes" public var animals: [Animal] @@ -14,7 +14,7 @@ extension Classes { } } - public struct Animal: PklRegisteredType, Decodable, Hashable { + public struct Animal: PklRegisteredType, Decodable, Hashable, @unchecked Sendable { public static let registeredIdentifier: String = "Classes#Animal" public var name: String diff --git a/Tests/PklSwiftTests/Fixtures/Generated/Collections.pkl.swift b/Tests/PklSwiftTests/Fixtures/Generated/Collections.pkl.swift index 6b28d5b..6357c59 100644 --- a/Tests/PklSwiftTests/Fixtures/Generated/Collections.pkl.swift +++ b/Tests/PklSwiftTests/Fixtures/Generated/Collections.pkl.swift @@ -4,7 +4,7 @@ import PklSwift public enum Collections {} extension Collections { - public struct Module: PklRegisteredType, Decodable, Hashable { + public struct Module: PklRegisteredType, Decodable, Hashable, @unchecked Sendable { public static let registeredIdentifier: String = "Collections" public var res1: [Int] diff --git a/Tests/PklSwiftTests/Fixtures/Generated/Collections2.pkl.swift b/Tests/PklSwiftTests/Fixtures/Generated/Collections2.pkl.swift index 445c6d2..d127286 100644 --- a/Tests/PklSwiftTests/Fixtures/Generated/Collections2.pkl.swift +++ b/Tests/PklSwiftTests/Fixtures/Generated/Collections2.pkl.swift @@ -4,7 +4,7 @@ import PklSwift public enum Collections2 {} extension Collections2 { - public struct Module: PklRegisteredType, Decodable, Hashable { + public struct Module: PklRegisteredType, Decodable, Hashable, @unchecked Sendable { public static let registeredIdentifier: String = "Collections2" public var res: [UInt8] diff --git a/Tests/PklSwiftTests/Fixtures/Generated/UnionTypes.pkl.swift b/Tests/PklSwiftTests/Fixtures/Generated/UnionTypes.pkl.swift index 5f8b182..d50f019 100644 --- a/Tests/PklSwiftTests/Fixtures/Generated/UnionTypes.pkl.swift +++ b/Tests/PklSwiftTests/Fixtures/Generated/UnionTypes.pkl.swift @@ -11,7 +11,7 @@ public protocol UnionTypes_Shape: PklRegisteredType, DynamicallyEquatable, Hasha } extension UnionTypes { - public enum Fruit: Decodable, Hashable { + public enum Fruit: Decodable, Hashable, Sendable { case banana(Banana) case grape(Grape) case apple(Apple) @@ -38,14 +38,14 @@ extension UnionTypes { } } - public enum City: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable { + public enum City: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable, Sendable { case sanFrancisco = "San Francisco" case tokyo = "Tokyo" case zurich = "Zurich" case london = "London" } - public enum ZebraOrDonkey: Decodable, Hashable { + public enum ZebraOrDonkey: Decodable, Hashable, Sendable { case zebra(Zebra) case donkey(Donkey) @@ -69,7 +69,7 @@ extension UnionTypes { } } - public enum AnimalOrString: Decodable, Hashable { + public enum AnimalOrString: Decodable, Hashable, Sendable { case animal(any Animal) case string(String) @@ -113,7 +113,7 @@ extension UnionTypes { } } - public enum IntOrFloat: Decodable, Hashable { + public enum IntOrFloat: Decodable, Hashable, Sendable { case int(Int) case float64(Float64) @@ -140,13 +140,13 @@ extension UnionTypes { } } - public enum Environment: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable { + public enum Environment: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable, Sendable { case dev = "dev" case prod = "prod" case qa = "qa" } - public enum AnimalOrShape: Decodable, Hashable { + public enum AnimalOrShape: Decodable, Hashable, Sendable { case animal(any Animal) case shape(any Shape) @@ -190,7 +190,7 @@ extension UnionTypes { } } - public enum Numbers: Decodable, Hashable { + public enum Numbers: Decodable, Hashable, Sendable { case int8(Int8) case int16(Int16) case int32(Int32) @@ -221,7 +221,7 @@ extension UnionTypes { } } - public struct Module: PklRegisteredType, Decodable, Hashable { + public struct Module: PklRegisteredType, Decodable, Hashable, @unchecked Sendable { public static let registeredIdentifier: String = "UnionTypes" public var fruit1: Fruit @@ -313,7 +313,7 @@ extension UnionTypes { } } - public struct Banana: PklRegisteredType, Decodable, Hashable { + public struct Banana: PklRegisteredType, Decodable, Hashable, @unchecked Sendable { public static let registeredIdentifier: String = "UnionTypes#Banana" public var isRipe: Bool @@ -323,7 +323,7 @@ extension UnionTypes { } } - public struct Grape: PklRegisteredType, Decodable, Hashable { + public struct Grape: PklRegisteredType, Decodable, Hashable, @unchecked Sendable { public static let registeredIdentifier: String = "UnionTypes#Grape" public var isUsedForWine: Bool @@ -333,7 +333,7 @@ extension UnionTypes { } } - public struct Apple: PklRegisteredType, Decodable, Hashable { + public struct Apple: PklRegisteredType, Decodable, Hashable, @unchecked Sendable { public static let registeredIdentifier: String = "UnionTypes#Apple" public var isRed: Bool diff --git a/Tests/PklSwiftTests/Fixtures/Generated/pkl_swift_example_Poly.pkl.swift b/Tests/PklSwiftTests/Fixtures/Generated/pkl_swift_example_Poly.pkl.swift index c437575..2846747 100644 --- a/Tests/PklSwiftTests/Fixtures/Generated/pkl_swift_example_Poly.pkl.swift +++ b/Tests/PklSwiftTests/Fixtures/Generated/pkl_swift_example_Poly.pkl.swift @@ -8,7 +8,7 @@ public protocol pkl_swift_example_Poly_Animal: pkl_swift_lib1_Being { } extension pkl_swift_example_Poly { - public struct Module: PklRegisteredType, Decodable, Hashable { + public struct Module: PklRegisteredType, Decodable, Hashable, @unchecked Sendable { public static let registeredIdentifier: String = "pkl.swift.example.Poly" public var beings: [any pkl_swift_lib1.Being] diff --git a/Tests/PklSwiftTests/Fixtures/Generated/pkl_swift_lib1.pkl.swift b/Tests/PklSwiftTests/Fixtures/Generated/pkl_swift_lib1.pkl.swift index 81c0350..ff11aa5 100644 --- a/Tests/PklSwiftTests/Fixtures/Generated/pkl_swift_lib1.pkl.swift +++ b/Tests/PklSwiftTests/Fixtures/Generated/pkl_swift_lib1.pkl.swift @@ -10,7 +10,7 @@ public protocol pkl_swift_lib1_Being: PklRegisteredType, DynamicallyEquatable, H extension pkl_swift_lib1 { public typealias Being = pkl_swift_lib1_Being - public struct Module: PklRegisteredType, Decodable, Hashable { + public struct Module: PklRegisteredType, Decodable, Hashable, @unchecked Sendable { public static let registeredIdentifier: String = "pkl.swift.lib1" public init() {} diff --git a/codegen/src/internal/ClassGen.pkl b/codegen/src/internal/ClassGen.pkl index 687c14c..b55d0b9 100644 --- a/codegen/src/internal/ClassGen.pkl +++ b/codegen/src/internal/ClassGen.pkl @@ -139,7 +139,7 @@ local structSuperclasses: String = else "\(superClass.namespaceName).\(superClass.name)" else - "PklRegisteredType, Decodable, Hashable" + "PklRegisteredType, Decodable, Hashable, @unchecked Sendable" local struct: String = new Listing { when (clazz.docComment != null) { diff --git a/codegen/src/internal/EnumGen.pkl b/codegen/src/internal/EnumGen.pkl index 948ecff..f12a6ac 100644 --- a/codegen/src/internal/EnumGen.pkl +++ b/codegen/src/internal/EnumGen.pkl @@ -71,7 +71,7 @@ local stringLiteralEnumContents = when (alias.docComment != null) { utils.renderDocComment(alias.docComment!!, "") } - "public enum \(module.mapping.name): String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable {" + "public enum \(module.mapping.name): String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable, Sendable {" for (member in enumStringLiteralMembers) { "\(module.indent)case \(member.name) = \(utils.toSwiftString((member.pklType as reflect.StringLiteralType).value))" } @@ -83,7 +83,7 @@ local enumContents = when (alias.docComment != null) { utils.renderDocComment(alias.docComment!!, "") } - "public enum \(module.mapping.name): Decodable, Hashable {" + "public enum \(module.mapping.name): Decodable, Hashable, Sendable {" for (member: EnumMember in enumNormalMembers) { "\(module.indent)case \(member.name)(\(member.renderedType))" } From b7ba4f4c475fb1b906ec3b825cc9e5bc94c3c826 Mon Sep 17 00:00:00 2001 From: Islon Scherer Date: Mon, 18 Aug 2025 14:32:07 +0200 Subject: [PATCH 2/5] Update CI to use Swift 6 --- .circleci/config.pkl | 2 +- .circleci/config.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.pkl b/.circleci/config.pkl index 8cddd54..a46a29a 100644 --- a/.circleci/config.pkl +++ b/.circleci/config.pkl @@ -125,7 +125,7 @@ jobs { ["test-pkl-\(distribution.normalizedVersion)"] { docker { new { - image = "swift:5.10-rhel-ubi9" + image = "swift:6.1-rhel-ubi9" } } resource_class = "xlarge" diff --git a/.circleci/config.yml b/.circleci/config.yml index 20df2d9..f2f3ad9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -24,7 +24,7 @@ jobs: path: .out/test-results/ resource_class: xlarge docker: - - image: swift:5.10-rhel-ubi9 + - image: swift:6.1-rhel-ubi9 test-pkl-0-29-0: steps: - checkout @@ -52,7 +52,7 @@ jobs: path: .out/test-results/ resource_class: xlarge docker: - - image: swift:5.10-rhel-ubi9 + - image: swift:6.1-rhel-ubi9 test-license-headers: steps: - checkout From 100987375046e707dc0bb334f3eaf059507d7b67 Mon Sep 17 00:00:00 2001 From: Islon Scherer Date: Mon, 18 Aug 2025 14:36:27 +0200 Subject: [PATCH 3/5] Fix swift update --- .circleci/config.pkl | 4 ++-- .circleci/config.yml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.circleci/config.pkl b/.circleci/config.pkl index a46a29a..d8f8148 100644 --- a/.circleci/config.pkl +++ b/.circleci/config.pkl @@ -163,7 +163,7 @@ jobs { ["test-format"] { docker { new { - image = "swift:5.10-rhel-ubi9" + image = "swift:6.1-rhel-ubi9" } } steps { @@ -197,7 +197,7 @@ jobs { ["pkl-gen-swift-linux-\(arch)"] { docker { new { - image = "swift:5.10-rhel-ubi9" + image = "swift:6.1-rhel-ubi9" } } resource_class = if (arch == "amd64") "xlarge" else "arm.xlarge" diff --git a/.circleci/config.yml b/.circleci/config.yml index f2f3ad9..51d4cec 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -66,7 +66,7 @@ jobs: - run: command: make swiftformat-lint docker: - - image: swift:5.10-rhel-ubi9 + - image: swift:6.1-rhel-ubi9 pkl-gen-swift-macos: steps: - checkout @@ -98,7 +98,7 @@ jobs: - out/ resource_class: arm.xlarge docker: - - image: swift:5.10-rhel-ubi9 + - image: swift:6.1-rhel-ubi9 pkl-gen-swift-linux-amd64: steps: - checkout @@ -114,7 +114,7 @@ jobs: - out/ resource_class: xlarge docker: - - image: swift:5.10-rhel-ubi9 + - image: swift:6.1-rhel-ubi9 pkl-package: steps: - checkout From 427da443db1e075a139149eb18fd4ef8354ec7d0 Mon Sep 17 00:00:00 2001 From: Islon Scherer Date: Mon, 18 Aug 2025 14:43:55 +0200 Subject: [PATCH 4/5] Fix concurrency error --- Sources/PklSwift/Utils.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/PklSwift/Utils.swift b/Sources/PklSwift/Utils.swift index 97b3b38..1906abe 100644 --- a/Sources/PklSwift/Utils.swift +++ b/Sources/PklSwift/Utils.swift @@ -23,7 +23,7 @@ func debug(_ message: @autoclosure @Sendable () -> String) { return } FileHandle.standardError.write("[pkl-swift] \(message())\n".data(using: .utf8)!) - fflush(stderr) + try? FileHandle.standardError.synchronize() } let longNumberFormatter: NumberFormatter = { From d66aa84f1d1805b369e50984af511d22085f6f61 Mon Sep 17 00:00:00 2001 From: Islon Scherer Date: Mon, 18 Aug 2025 14:50:16 +0200 Subject: [PATCH 5/5] Fix snippets --- codegen/snippet-tests/output/Classes.pkl.swift | 2 +- codegen/snippet-tests/output/Enums.pkl.swift | 18 +++++++++--------- .../output/ExplicitlyCoolName.pkl.swift | 6 +++--- .../output/ExtendingOpenClass.pkl.swift | 2 +- .../output/ExtendsAbstractClass.pkl.swift | 2 +- codegen/snippet-tests/output/Foo.pkl.swift | 2 +- .../output/HiddenProperties.pkl.swift | 2 +- codegen/snippet-tests/output/Imports.pkl.swift | 2 +- .../snippet-tests/output/TypeAliased.pkl.swift | 2 +- .../output/UnionNameKeyword.pkl.swift | 4 ++-- .../com_example_ExtendedSimple.pkl.swift | 2 +- .../output/com_example_Simple.pkl.swift | 4 ++-- codegen/snippet-tests/output/lib3.pkl.swift | 2 +- .../snippet-tests/output/override.pkl.swift | 2 +- codegen/snippet-tests/output/union.pkl.swift | 10 +++++----- 15 files changed, 31 insertions(+), 31 deletions(-) diff --git a/codegen/snippet-tests/output/Classes.pkl.swift b/codegen/snippet-tests/output/Classes.pkl.swift index 542f76d..05c7b9f 100644 --- a/codegen/snippet-tests/output/Classes.pkl.swift +++ b/codegen/snippet-tests/output/Classes.pkl.swift @@ -8,7 +8,7 @@ public protocol Classes_Animal: PklRegisteredType, DynamicallyEquatable, Hashabl } extension Classes { - public struct Module: PklRegisteredType, Decodable, Hashable { + public struct Module: PklRegisteredType, Decodable, Hashable, @unchecked Sendable { public static let registeredIdentifier: String = "Classes" public var animals: [any Animal] diff --git a/codegen/snippet-tests/output/Enums.pkl.swift b/codegen/snippet-tests/output/Enums.pkl.swift index eb9e805..d8685e6 100644 --- a/codegen/snippet-tests/output/Enums.pkl.swift +++ b/codegen/snippet-tests/output/Enums.pkl.swift @@ -5,7 +5,7 @@ public enum Enums {} extension Enums { /// City is one of these four fantastic cities - public enum City: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable { + public enum City: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable, Sendable { case sanFrancisco = "San Francisco" case london = "London" case zurich = "Zurich" @@ -13,7 +13,7 @@ extension Enums { } /// Animal is either a horse, monkey, or zebra - public enum Animal: Decodable, Hashable { + public enum Animal: Decodable, Hashable, Sendable { case horse(Horse) case zebra(Zebra) case monkey(Monkey) @@ -41,7 +41,7 @@ extension Enums { } /// Either a dictionary or an array. - public enum DictOrArray: Decodable, Hashable { + public enum DictOrArray: Decodable, Hashable, Sendable { case dictionaryStringString([String: String]) case arrayString([String]) @@ -65,7 +65,7 @@ extension Enums { } } - public enum HorseOrBug: Decodable, Hashable { + public enum HorseOrBug: Decodable, Hashable, Sendable { case horse(Horse) case string(String) case string(String) @@ -92,7 +92,7 @@ extension Enums { } } - public enum MaybeHorseOrDefinitelyZebra: Decodable, Hashable { + public enum MaybeHorseOrDefinitelyZebra: Decodable, Hashable, Sendable { case horse(Horse?) case zebra(Zebra) @@ -116,7 +116,7 @@ extension Enums { } } - public struct Module: PklRegisteredType, Decodable, Hashable { + public struct Module: PklRegisteredType, Decodable, Hashable, @unchecked Sendable { public static let registeredIdentifier: String = "Enums" /// City of tomorrow! @@ -148,7 +148,7 @@ extension Enums { } } - public struct Horse: PklRegisteredType, Decodable, Hashable { + public struct Horse: PklRegisteredType, Decodable, Hashable, @unchecked Sendable { public static let registeredIdentifier: String = "Enums#Horse" public var neigh: Bool @@ -158,7 +158,7 @@ extension Enums { } } - public struct Zebra: PklRegisteredType, Decodable, Hashable { + public struct Zebra: PklRegisteredType, Decodable, Hashable, @unchecked Sendable { public static let registeredIdentifier: String = "Enums#Zebra" public var stripes: String @@ -168,7 +168,7 @@ extension Enums { } } - public struct Monkey: PklRegisteredType, Decodable, Hashable { + public struct Monkey: PklRegisteredType, Decodable, Hashable, @unchecked Sendable { public static let registeredIdentifier: String = "Enums#Monkey" public var tail: String diff --git a/codegen/snippet-tests/output/ExplicitlyCoolName.pkl.swift b/codegen/snippet-tests/output/ExplicitlyCoolName.pkl.swift index 2036011..dcf0bc8 100644 --- a/codegen/snippet-tests/output/ExplicitlyCoolName.pkl.swift +++ b/codegen/snippet-tests/output/ExplicitlyCoolName.pkl.swift @@ -4,12 +4,12 @@ import PklSwift public enum ExplicitlyCoolName {} extension ExplicitlyCoolName { - public enum ConfigType: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable { + public enum ConfigType: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable, Sendable { case one = "one" case two = "two" } - public struct Module: PklRegisteredType, Decodable, Hashable { + public struct Module: PklRegisteredType, Decodable, Hashable, @unchecked Sendable { public static let registeredIdentifier: String = "ExplicitName" public var MyCoolProp: SomethingVeryFunny @@ -23,7 +23,7 @@ extension ExplicitlyCoolName { } } - public struct SomethingVeryFunny: PklRegisteredType, Decodable, Hashable { + public struct SomethingVeryFunny: PklRegisteredType, Decodable, Hashable, @unchecked Sendable { public static let registeredIdentifier: String = "ExplicitName#SomethingFunny" public init() {} diff --git a/codegen/snippet-tests/output/ExtendingOpenClass.pkl.swift b/codegen/snippet-tests/output/ExtendingOpenClass.pkl.swift index ec82eda..3fc5231 100644 --- a/codegen/snippet-tests/output/ExtendingOpenClass.pkl.swift +++ b/codegen/snippet-tests/output/ExtendingOpenClass.pkl.swift @@ -8,7 +8,7 @@ public protocol ExtendingOpenClass_MyOpenClass: PklRegisteredType, DynamicallyEq } extension ExtendingOpenClass { - public struct Module: PklRegisteredType, Decodable, Hashable { + public struct Module: PklRegisteredType, Decodable, Hashable, @unchecked Sendable { public static let registeredIdentifier: String = "ExtendingOpenClass" public var res1: MyClass diff --git a/codegen/snippet-tests/output/ExtendsAbstractClass.pkl.swift b/codegen/snippet-tests/output/ExtendsAbstractClass.pkl.swift index e2ae987..1c1ac2d 100644 --- a/codegen/snippet-tests/output/ExtendsAbstractClass.pkl.swift +++ b/codegen/snippet-tests/output/ExtendsAbstractClass.pkl.swift @@ -8,7 +8,7 @@ public protocol ExtendsAbstractClass_A: PklRegisteredType, DynamicallyEquatable, } extension ExtendsAbstractClass { - public struct Module: PklRegisteredType, Decodable, Hashable { + public struct Module: PklRegisteredType, Decodable, Hashable, @unchecked Sendable { public static let registeredIdentifier: String = "ExtendsAbstractClass" public var a: any A diff --git a/codegen/snippet-tests/output/Foo.pkl.swift b/codegen/snippet-tests/output/Foo.pkl.swift index 7f29dc9..4aee093 100644 --- a/codegen/snippet-tests/output/Foo.pkl.swift +++ b/codegen/snippet-tests/output/Foo.pkl.swift @@ -12,7 +12,7 @@ public protocol Foo_Being: PklRegisteredType, DynamicallyEquatable, Hashable { } extension Foo { - public struct Module: PklRegisteredType, Decodable, Hashable { + public struct Module: PklRegisteredType, Decodable, Hashable, @unchecked Sendable { public static let registeredIdentifier: String = "Foo" public var animals: [any Animal] diff --git a/codegen/snippet-tests/output/HiddenProperties.pkl.swift b/codegen/snippet-tests/output/HiddenProperties.pkl.swift index 2354459..d77fe4b 100644 --- a/codegen/snippet-tests/output/HiddenProperties.pkl.swift +++ b/codegen/snippet-tests/output/HiddenProperties.pkl.swift @@ -4,7 +4,7 @@ import PklSwift public enum HiddenProperties {} extension HiddenProperties { - public struct Module: PklRegisteredType, Decodable, Hashable { + public struct Module: PklRegisteredType, Decodable, Hashable, @unchecked Sendable { public static let registeredIdentifier: String = "HiddenProperties" public var propC: String diff --git a/codegen/snippet-tests/output/Imports.pkl.swift b/codegen/snippet-tests/output/Imports.pkl.swift index 69026ef..527b64c 100644 --- a/codegen/snippet-tests/output/Imports.pkl.swift +++ b/codegen/snippet-tests/output/Imports.pkl.swift @@ -4,7 +4,7 @@ import PklSwift public enum Imports {} extension Imports { - public struct Module: PklRegisteredType, Decodable, Hashable { + public struct Module: PklRegisteredType, Decodable, Hashable, @unchecked Sendable { public static let registeredIdentifier: String = "Imports" public var foo: Foo.Module diff --git a/codegen/snippet-tests/output/TypeAliased.pkl.swift b/codegen/snippet-tests/output/TypeAliased.pkl.swift index 2dabd0d..3637a78 100644 --- a/codegen/snippet-tests/output/TypeAliased.pkl.swift +++ b/codegen/snippet-tests/output/TypeAliased.pkl.swift @@ -4,7 +4,7 @@ import PklSwift public enum TypeAliased {} extension TypeAliased { - public struct Module: PklRegisteredType, Decodable, Hashable { + public struct Module: PklRegisteredType, Decodable, Hashable, @unchecked Sendable { public static let registeredIdentifier: String = "TypeAliased" public var myMap: StringyMap diff --git a/codegen/snippet-tests/output/UnionNameKeyword.pkl.swift b/codegen/snippet-tests/output/UnionNameKeyword.pkl.swift index 5bdc01e..9f48533 100644 --- a/codegen/snippet-tests/output/UnionNameKeyword.pkl.swift +++ b/codegen/snippet-tests/output/UnionNameKeyword.pkl.swift @@ -4,13 +4,13 @@ import PklSwift public enum UnionNameKeyword {} extension UnionNameKeyword { - public enum `Type`: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable { + public enum `Type`: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable, Sendable { case one = "one" case two = "two" case three = "three" } - public struct Module: PklRegisteredType, Decodable, Hashable { + public struct Module: PklRegisteredType, Decodable, Hashable, @unchecked Sendable { public static let registeredIdentifier: String = "UnionNameKeyword" public var type: `Type` diff --git a/codegen/snippet-tests/output/com_example_ExtendedSimple.pkl.swift b/codegen/snippet-tests/output/com_example_ExtendedSimple.pkl.swift index cd2422e..a593bbc 100644 --- a/codegen/snippet-tests/output/com_example_ExtendedSimple.pkl.swift +++ b/codegen/snippet-tests/output/com_example_ExtendedSimple.pkl.swift @@ -4,7 +4,7 @@ import PklSwift public enum com_example_ExtendedSimple {} extension com_example_ExtendedSimple { - public struct Module: PklRegisteredType, Decodable, Hashable { + public struct Module: PklRegisteredType, Decodable, Hashable, @unchecked Sendable { public static let registeredIdentifier: String = "com.example.ExtendedSimple" public init() {} diff --git a/codegen/snippet-tests/output/com_example_Simple.pkl.swift b/codegen/snippet-tests/output/com_example_Simple.pkl.swift index a795bfb..58bd350 100644 --- a/codegen/snippet-tests/output/com_example_Simple.pkl.swift +++ b/codegen/snippet-tests/output/com_example_Simple.pkl.swift @@ -14,7 +14,7 @@ public protocol com_example_Simple_OpenClassExtendingOpenClass: PklRegisteredTyp } extension com_example_Simple { - public struct Module: PklRegisteredType, Decodable, Hashable { + public struct Module: PklRegisteredType, Decodable, Hashable, @unchecked Sendable { public static let registeredIdentifier: String = "com.example.Simple" /// This is truly a person. @@ -98,7 +98,7 @@ extension com_example_Simple { } } - public struct ClassWithReallyLongConstructor: PklRegisteredType, Decodable, Hashable { + public struct ClassWithReallyLongConstructor: PklRegisteredType, Decodable, Hashable, @unchecked Sendable { public static let registeredIdentifier: String = "com.example.Simple#ClassWithReallyLongConstructor" public var theProperty1: String diff --git a/codegen/snippet-tests/output/lib3.pkl.swift b/codegen/snippet-tests/output/lib3.pkl.swift index add7b9e..eea196d 100644 --- a/codegen/snippet-tests/output/lib3.pkl.swift +++ b/codegen/snippet-tests/output/lib3.pkl.swift @@ -20,7 +20,7 @@ extension lib3 { } } - public struct Module: PklRegisteredType, Decodable, Hashable { + public struct Module: PklRegisteredType, Decodable, Hashable, @unchecked Sendable { public static let registeredIdentifier: String = "lib3" public init() {} diff --git a/codegen/snippet-tests/output/override.pkl.swift b/codegen/snippet-tests/output/override.pkl.swift index 036729c..8899c87 100644 --- a/codegen/snippet-tests/output/override.pkl.swift +++ b/codegen/snippet-tests/output/override.pkl.swift @@ -8,7 +8,7 @@ public protocol override_Foo: PklRegisteredType, DynamicallyEquatable, Hashable } extension override { - public struct Module: PklRegisteredType, Decodable, Hashable { + public struct Module: PklRegisteredType, Decodable, Hashable, @unchecked Sendable { public static let registeredIdentifier: String = "override" public var foo: any Foo diff --git a/codegen/snippet-tests/output/union.pkl.swift b/codegen/snippet-tests/output/union.pkl.swift index 82621a0..df9c48e 100644 --- a/codegen/snippet-tests/output/union.pkl.swift +++ b/codegen/snippet-tests/output/union.pkl.swift @@ -5,35 +5,35 @@ public enum union {} extension union { /// City; e.g. where people live - public enum City: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable { + public enum City: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable, Sendable { case sanFrancisco = "San Francisco" case london = "London" case 上海 = "上海" } /// Locale that contains cities and towns - public enum County: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable { + public enum County: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable, Sendable { case sanFrancisco = "San Francisco" case sanMateo = "San Mateo" case yolo = "Yolo" } /// Noodles - public enum Noodles: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable { + public enum Noodles: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable, Sendable { case 拉面 = "拉面" case 刀切面 = "刀切面" case 面线 = "面线" case 意大利面 = "意大利面" } - public enum AccountDisposition: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable { + public enum AccountDisposition: String, CaseIterable, CodingKeyRepresentable, Decodable, Hashable, Sendable { case empty = "" case icloud3 = "icloud3" case prod = "prod" case shared = "shared" } - public struct Module: PklRegisteredType, Decodable, Hashable { + public struct Module: PklRegisteredType, Decodable, Hashable, @unchecked Sendable { public static let registeredIdentifier: String = "union" /// A city