Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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
}

Expand Down
21 changes: 13 additions & 8 deletions Sources/Configuration/Utilities/AsyncSequences.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,18 @@

/// A concrete async sequence for delivering updated configuration values.
@available(Configuration 1.0, *)
public struct ConfigUpdatesAsyncSequence<Element: Sendable, Failure: Error> {
public struct ConfigUpdatesAsyncSequence<Element: Sendable, Failure: Error>: 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<Element, Failure>
private let upstream: any AsyncSequence<Element, Failure> & Sendable

/// Creates a new concrete async sequence wrapping the provided existential sequence.
///
/// - Parameter upstream: The async sequence to wrap.
public init(_ upstream: some AsyncSequence<Element, Failure>) {
public init(_ upstream: some AsyncSequence<Element, Failure> & Sendable) {
self.upstream = upstream
}
}
Expand Down Expand Up @@ -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.
///
Expand Down Expand Up @@ -89,8 +89,8 @@ extension AsyncSequence where Failure == Never {
/// }
/// ```
func mapThrowing<NewValue, Failure: Error>(
_ transform: @escaping (Element) throws(Failure) -> NewValue
) -> some AsyncSequence<NewValue, Failure> {
_ transform: @escaping @Sendable (Element) throws(Failure) -> NewValue
) -> some AsyncSequence<NewValue, Failure> & Sendable {
MapThrowingAsyncSequence(upstream: self, transform: transform)
}
}
Expand All @@ -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<Element, Failure: Error, Value, Upstream: AsyncSequence<Value, Never>> {
private struct MapThrowingAsyncSequence<
Element,
Failure: Error,
Value,
Upstream: AsyncSequence<Value, Never> & 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, *)
Expand Down
Loading