diff --git a/Package.swift b/Package.swift index 71e126b..4ec337d 100644 --- a/Package.swift +++ b/Package.swift @@ -61,6 +61,7 @@ let enableAllTraitsExplicit = ProcessInfo.processInfo.environment["ENABLE_ALL_TR let enableAllTraits = spiGenerateDocs || previewDocs || enableAllTraitsExplicit let addDoccPlugin = previewDocs || spiGenerateDocs +let enableCIFlags = enableAllTraitsExplicit traits.insert( .default( @@ -179,8 +180,14 @@ for target in package.targets { // https://github.com/swiftlang/swift-evolution/blob/main/proposals/0409-access-level-on-imports.md settings.append(.enableUpcomingFeature("InternalImportsByDefault")) + // Availability macro settings.append(.enableExperimentalFeature("AvailabilityMacro=Configuration 1.0:macOS 15.0, iOS 18.0, watchOS 11.0, tvOS 18.0, visionOS 2.0")) + if enableCIFlags { + // Ensure all public types are explicitly annotated as Sendable or not Sendable. + settings.append(.unsafeFlags(["-Xfrontend", "-require-explicit-sendable"])) + } + target.swiftSettings = settings } diff --git a/Sources/Configuration/Utilities/AsyncSequences.swift b/Sources/Configuration/Utilities/AsyncSequences.swift index 260a981..75b2b36 100644 --- a/Sources/Configuration/Utilities/AsyncSequences.swift +++ b/Sources/Configuration/Utilities/AsyncSequences.swift @@ -14,18 +14,18 @@ /// A concrete async sequence for delivering updated configuration values. @available(Configuration 1.0, *) -public struct ConfigUpdatesAsyncSequence { +public struct ConfigUpdatesAsyncSequence: Sendable { /// The upstream async sequence that this concrete sequence wraps. /// /// This property holds the async sequence that provides the actual elements. /// All operations on this concrete sequence are delegated to this upstream sequence. - private let upstream: any AsyncSequence + private let upstream: any AsyncSequence & Sendable /// Creates a new concrete async sequence wrapping the provided existential sequence. /// /// - Parameter upstream: The async sequence to wrap. - public init(_ upstream: some AsyncSequence) { + public init(_ upstream: some AsyncSequence & Sendable) { self.upstream = upstream } } @@ -60,7 +60,7 @@ extension ConfigUpdatesAsyncSequence: AsyncSequence { // MARK: - AsyncSequence extensions @available(Configuration 1.0, *) -extension AsyncSequence where Failure == Never { +extension AsyncSequence where Failure == Never, Self: Sendable { /// Maps each element of the sequence using a throwing transform, introducing a failure type. /// @@ -89,8 +89,8 @@ extension AsyncSequence where Failure == Never { /// } /// ``` func mapThrowing( - _ transform: @escaping (Element) throws(Failure) -> NewValue - ) -> some AsyncSequence { + _ transform: @escaping @Sendable (Element) throws(Failure) -> NewValue + ) -> some AsyncSequence & Sendable { MapThrowingAsyncSequence(upstream: self, transform: transform) } } @@ -110,13 +110,18 @@ extension AsyncSequence where Failure == Never { /// - `Value`: The input element type from the upstream sequence. /// - `Upstream`: The upstream async sequence type that never throws. @available(Configuration 1.0, *) -private struct MapThrowingAsyncSequence> { +private struct MapThrowingAsyncSequence< + Element, + Failure: Error, + Value, + Upstream: AsyncSequence & Sendable +>: Sendable { /// The upstream async sequence to transform. var upstream: Upstream /// The throwing transform function to apply to each element. - var transform: (Value) throws(Failure) -> Element + var transform: @Sendable (Value) throws(Failure) -> Element } @available(Configuration 1.0, *)