Skip to content

Commit f5fd053

Browse files
committed
Move platform requirements to availability annotations
Adding or raising the deployment platforms in the package manifest is a SemVer major breaking change as consumers must also add or raise their deployment platforms. This is a known limitation of SwiftPM. Unforunately this means that it's very difficult for non-leaf packages to adopt packages which declare their platforms in the manifest. Doing so puts the brakes on adoption and ecosystem growth. For 'core' packages like this one availability constraints should be expressed on declarations rather than in the manifest. This patch adds equivalent availability annotations to declarations across the package and removes platforms from the package manifest.
1 parent 57b0814 commit f5fd053

File tree

56 files changed

+224
-13
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+224
-13
lines changed

Package.swift

+34-10
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,39 @@
11
// swift-tools-version: 5.8
22

33
import PackageDescription
4+
import CompilerPluginSupport
5+
6+
// Availability Macros
7+
let availabilityTags = [_Availability("AsyncAlgorithms")]
8+
let versionNumbers = ["1.0"]
9+
10+
// Availability Macro Utilities
11+
enum _OSAvailability: String {
12+
// This should match the package's deployment target
13+
case alwaysAvailable = "macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0"
14+
// Use 10000 for future availability to avoid compiler magic around
15+
// the 9999 version number but ensure it is greater than 9999
16+
case future = "macOS 10000, iOS 10000, tvOS 10000, watchOS 10000"
17+
}
18+
19+
struct _Availability {
20+
let name: String
21+
let osAvailability: _OSAvailability
22+
23+
init(_ name: String, availability: _OSAvailability = .alwaysAvailable) {
24+
self.name = name
25+
self.osAvailability = availability
26+
}
27+
}
28+
29+
let availabilityMacros: [SwiftSetting] = versionNumbers.flatMap { version in
30+
availabilityTags.map {
31+
.enableExperimentalFeature("AvailabilityMacro=\($0.name) \(version):\($0.osAvailability.rawValue)")
32+
}
33+
}
434

535
let package = Package(
636
name: "swift-async-algorithms",
7-
platforms: [
8-
.macOS("10.15"),
9-
.iOS("13.0"),
10-
.tvOS("13.0"),
11-
.watchOS("6.0"),
12-
],
1337
products: [
1438
.library(name: "AsyncAlgorithms", targets: ["AsyncAlgorithms"])
1539
],
@@ -20,29 +44,29 @@ let package = Package(
2044
.product(name: "OrderedCollections", package: "swift-collections"),
2145
.product(name: "DequeModule", package: "swift-collections"),
2246
],
23-
swiftSettings: [
47+
swiftSettings: availabilityMacros + [
2448
.enableExperimentalFeature("StrictConcurrency=complete")
2549
]
2650
),
2751
.target(
2852
name: "AsyncSequenceValidation",
2953
dependencies: ["_CAsyncSequenceValidationSupport", "AsyncAlgorithms"],
30-
swiftSettings: [
54+
swiftSettings: availabilityMacros + [
3155
.enableExperimentalFeature("StrictConcurrency=complete")
3256
]
3357
),
3458
.systemLibrary(name: "_CAsyncSequenceValidationSupport"),
3559
.target(
3660
name: "AsyncAlgorithms_XCTest",
3761
dependencies: ["AsyncAlgorithms", "AsyncSequenceValidation"],
38-
swiftSettings: [
62+
swiftSettings: availabilityMacros + [
3963
.enableExperimentalFeature("StrictConcurrency=complete")
4064
]
4165
),
4266
.testTarget(
4367
name: "AsyncAlgorithmsTests",
4468
dependencies: ["AsyncAlgorithms", "AsyncSequenceValidation", "AsyncAlgorithms_XCTest"],
45-
swiftSettings: [
69+
swiftSettings: availabilityMacros + [
4670
.enableExperimentalFeature("StrictConcurrency=complete")
4771
]
4872
),

Sources/AsyncAlgorithms/AsyncAdjacentPairsSequence.swift

+4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
//
1010
//===----------------------------------------------------------------------===//
1111

12+
@available(AsyncAlgorithms 1.0, *)
1213
extension AsyncSequence {
1314
/// An `AsyncSequence` that iterates over the adjacent pairs of the original
1415
/// original `AsyncSequence`.
@@ -26,6 +27,7 @@ extension AsyncSequence {
2627
///
2728
/// - Returns: An `AsyncSequence` where the element is a tuple of two adjacent elements
2829
/// or the original `AsyncSequence`.
30+
@available(AsyncAlgorithms 1.0, *)
2931
@inlinable
3032
public func adjacentPairs() -> AsyncAdjacentPairsSequence<Self> {
3133
AsyncAdjacentPairsSequence(self)
@@ -34,6 +36,7 @@ extension AsyncSequence {
3436

3537
/// An `AsyncSequence` that iterates over the adjacent pairs of the original
3638
/// `AsyncSequence`.
39+
@available(AsyncAlgorithms 1.0, *)
3740
@frozen
3841
public struct AsyncAdjacentPairsSequence<Base: AsyncSequence>: AsyncSequence {
3942
public typealias Element = (Base.Element, Base.Element)
@@ -83,6 +86,7 @@ public struct AsyncAdjacentPairsSequence<Base: AsyncSequence>: AsyncSequence {
8386
}
8487
}
8588

89+
@available(AsyncAlgorithms 1.0, *)
8690
extension AsyncAdjacentPairsSequence: Sendable where Base: Sendable, Base.Element: Sendable {}
8791

8892
@available(*, unavailable)

Sources/AsyncAlgorithms/AsyncBufferedByteIterator.swift

+2
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
/// }
4040
///
4141
///
42+
@available(AsyncAlgorithms 1.0, *)
4243
public struct AsyncBufferedByteIterator: AsyncIteratorProtocol {
4344
public typealias Element = UInt8
4445
@usableFromInline var buffer: _AsyncBytesBuffer
@@ -67,6 +68,7 @@ public struct AsyncBufferedByteIterator: AsyncIteratorProtocol {
6768
@available(*, unavailable)
6869
extension AsyncBufferedByteIterator: Sendable {}
6970

71+
@available(AsyncAlgorithms 1.0, *)
7072
@frozen @usableFromInline
7173
internal struct _AsyncBytesBuffer {
7274
@usableFromInline

Sources/AsyncAlgorithms/AsyncChain2Sequence.swift

+6
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
/// - s2: The second asynchronous sequence.
1818
/// - Returns: An asynchronous sequence that iterates first over the elements of `s1`, and
1919
/// then over the elements of `s2`.
20+
@available(AsyncAlgorithms 1.0, *)
2021
@inlinable
2122
public func chain<Base1: AsyncSequence, Base2: AsyncSequence>(
2223
_ s1: Base1,
@@ -26,6 +27,7 @@ public func chain<Base1: AsyncSequence, Base2: AsyncSequence>(
2627
}
2728

2829
/// A concatenation of two asynchronous sequences with the same element type.
30+
@available(AsyncAlgorithms 1.0, *)
2931
@frozen
3032
public struct AsyncChain2Sequence<Base1: AsyncSequence, Base2: AsyncSequence> where Base1.Element == Base2.Element {
3133
@usableFromInline
@@ -41,10 +43,12 @@ public struct AsyncChain2Sequence<Base1: AsyncSequence, Base2: AsyncSequence> wh
4143
}
4244
}
4345

46+
@available(AsyncAlgorithms 1.0, *)
4447
extension AsyncChain2Sequence: AsyncSequence {
4548
public typealias Element = Base1.Element
4649

4750
/// The iterator for a `AsyncChain2Sequence` instance.
51+
@available(AsyncAlgorithms 1.0, *)
4852
@frozen
4953
public struct Iterator: AsyncIteratorProtocol {
5054
@usableFromInline
@@ -76,12 +80,14 @@ extension AsyncChain2Sequence: AsyncSequence {
7680
}
7781
}
7882

83+
@available(AsyncAlgorithms 1.0, *)
7984
@inlinable
8085
public func makeAsyncIterator() -> Iterator {
8186
Iterator(base1.makeAsyncIterator(), base2.makeAsyncIterator())
8287
}
8388
}
8489

90+
@available(AsyncAlgorithms 1.0, *)
8591
extension AsyncChain2Sequence: Sendable where Base1: Sendable, Base2: Sendable {}
8692

8793
@available(*, unavailable)

Sources/AsyncAlgorithms/AsyncChain3Sequence.swift

+6
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
/// - s3: The third asynchronous sequence.
1919
/// - Returns: An asynchronous sequence that iterates first over the elements of `s1`, and
2020
/// then over the elements of `s2`, and then over the elements of `s3`
21+
@available(AsyncAlgorithms 1.0, *)
2122
@inlinable
2223
public func chain<Base1: AsyncSequence, Base2: AsyncSequence, Base3: AsyncSequence>(
2324
_ s1: Base1,
@@ -28,6 +29,7 @@ public func chain<Base1: AsyncSequence, Base2: AsyncSequence, Base3: AsyncSequen
2829
}
2930

3031
/// A concatenation of three asynchronous sequences with the same element type.
32+
@available(AsyncAlgorithms 1.0, *)
3133
@frozen
3234
public struct AsyncChain3Sequence<Base1: AsyncSequence, Base2: AsyncSequence, Base3: AsyncSequence>
3335
where Base1.Element == Base2.Element, Base1.Element == Base3.Element {
@@ -48,10 +50,12 @@ where Base1.Element == Base2.Element, Base1.Element == Base3.Element {
4850
}
4951
}
5052

53+
@available(AsyncAlgorithms 1.0, *)
5154
extension AsyncChain3Sequence: AsyncSequence {
5255
public typealias Element = Base1.Element
5356

5457
/// The iterator for a `AsyncChain3Sequence` instance.
58+
@available(AsyncAlgorithms 1.0, *)
5559
@frozen
5660
public struct Iterator: AsyncIteratorProtocol {
5761
@usableFromInline
@@ -93,12 +97,14 @@ extension AsyncChain3Sequence: AsyncSequence {
9397
}
9498
}
9599

100+
@available(AsyncAlgorithms 1.0, *)
96101
@inlinable
97102
public func makeAsyncIterator() -> Iterator {
98103
Iterator(base1.makeAsyncIterator(), base2.makeAsyncIterator(), base3.makeAsyncIterator())
99104
}
100105
}
101106

107+
@available(AsyncAlgorithms 1.0, *)
102108
extension AsyncChain3Sequence: Sendable where Base1: Sendable, Base2: Sendable, Base3: Sendable {}
103109

104110
@available(*, unavailable)

Sources/AsyncAlgorithms/AsyncChunkedByGroupSequence.swift

+5
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@
99
//
1010
//===----------------------------------------------------------------------===//
1111

12+
@available(AsyncAlgorithms 1.0, *)
1213
extension AsyncSequence {
1314
/// Creates an asynchronous sequence that creates chunks of a given `RangeReplaceableCollection`
1415
/// type by testing if elements belong in the same group.
16+
@available(AsyncAlgorithms 1.0, *)
1517
@inlinable
1618
public func chunked<Collected: RangeReplaceableCollection>(
1719
into: Collected.Type,
@@ -21,6 +23,7 @@ extension AsyncSequence {
2123
}
2224

2325
/// Creates an asynchronous sequence that creates chunks by testing if elements belong in the same group.
26+
@available(AsyncAlgorithms 1.0, *)
2427
@inlinable
2528
public func chunked(
2629
by belongInSameGroup: @escaping @Sendable (Element, Element) -> Bool
@@ -51,6 +54,7 @@ extension AsyncSequence {
5154
/// // [10, 20, 30]
5255
/// // [10, 40, 40]
5356
/// // [10, 20]
57+
@available(AsyncAlgorithms 1.0, *)
5458
public struct AsyncChunkedByGroupSequence<Base: AsyncSequence, Collected: RangeReplaceableCollection>: AsyncSequence
5559
where Collected.Element == Base.Element {
5660
public typealias Element = Collected
@@ -121,6 +125,7 @@ where Collected.Element == Base.Element {
121125
}
122126
}
123127

128+
@available(AsyncAlgorithms 1.0, *)
124129
extension AsyncChunkedByGroupSequence: Sendable where Base: Sendable, Base.Element: Sendable {}
125130

126131
@available(*, unavailable)

Sources/AsyncAlgorithms/AsyncChunkedOnProjectionSequence.swift

+5
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
//
1010
//===----------------------------------------------------------------------===//
1111

12+
@available(AsyncAlgorithms 1.0, *)
1213
extension AsyncSequence {
1314
/// Creates an asynchronous sequence that creates chunks of a given `RangeReplaceableCollection` type on the uniqueness of a given subject.
15+
@available(AsyncAlgorithms 1.0, *)
1416
@inlinable
1517
public func chunked<Subject: Equatable, Collected: RangeReplaceableCollection>(
1618
into: Collected.Type,
@@ -20,6 +22,7 @@ extension AsyncSequence {
2022
}
2123

2224
/// Creates an asynchronous sequence that creates chunks on the uniqueness of a given subject.
25+
@available(AsyncAlgorithms 1.0, *)
2326
@inlinable
2427
public func chunked<Subject: Equatable>(
2528
on projection: @escaping @Sendable (Element) -> Subject
@@ -29,6 +32,7 @@ extension AsyncSequence {
2932
}
3033

3134
/// An `AsyncSequence` that chunks on a subject when it differs from the last element.
35+
@available(AsyncAlgorithms 1.0, *)
3236
public struct AsyncChunkedOnProjectionSequence<
3337
Base: AsyncSequence,
3438
Subject: Equatable,
@@ -104,6 +108,7 @@ public struct AsyncChunkedOnProjectionSequence<
104108
}
105109
}
106110

111+
@available(AsyncAlgorithms 1.0, *)
107112
extension AsyncChunkedOnProjectionSequence: Sendable where Base: Sendable, Base.Element: Sendable {}
108113

109114
@available(*, unavailable)

Sources/AsyncAlgorithms/AsyncChunksOfCountOrSignalSequence.swift

+6
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
//
1010
//===----------------------------------------------------------------------===//
1111

12+
@available(AsyncAlgorithms 1.0, *)
1213
extension AsyncSequence {
1314
/// Creates an asynchronous sequence that creates chunks of a given `RangeReplaceableCollection` type of a given count or when a signal `AsyncSequence` produces an element.
15+
@available(AsyncAlgorithms 1.0, *)
1416
public func chunks<Signal, Collected: RangeReplaceableCollection>(
1517
ofCount count: Int,
1618
or signal: Signal,
@@ -20,6 +22,7 @@ extension AsyncSequence {
2022
}
2123

2224
/// Creates an asynchronous sequence that creates chunks of a given count or when a signal `AsyncSequence` produces an element.
25+
@available(AsyncAlgorithms 1.0, *)
2326
public func chunks<Signal>(
2427
ofCount count: Int,
2528
or signal: Signal
@@ -28,6 +31,7 @@ extension AsyncSequence {
2831
}
2932

3033
/// Creates an asynchronous sequence that creates chunks of a given `RangeReplaceableCollection` type when a signal `AsyncSequence` produces an element.
34+
@available(AsyncAlgorithms 1.0, *)
3135
public func chunked<Signal, Collected: RangeReplaceableCollection>(
3236
by signal: Signal,
3337
into: Collected.Type
@@ -36,6 +40,7 @@ extension AsyncSequence {
3640
}
3741

3842
/// Creates an asynchronous sequence that creates chunks when a signal `AsyncSequence` produces an element.
43+
@available(AsyncAlgorithms 1.0, *)
3944
public func chunked<Signal>(by signal: Signal) -> AsyncChunksOfCountOrSignalSequence<Self, [Element], Signal> {
4045
chunked(by: signal, into: [Element].self)
4146
}
@@ -78,6 +83,7 @@ extension AsyncSequence {
7883
}
7984

8085
/// An `AsyncSequence` that chunks elements into collected `RangeReplaceableCollection` instances by either count or a signal from another `AsyncSequence`.
86+
@available(AsyncAlgorithms 1.0, *)
8187
public struct AsyncChunksOfCountOrSignalSequence<
8288
Base: AsyncSequence,
8389
Collected: RangeReplaceableCollection,

Sources/AsyncAlgorithms/AsyncChunksOfCountSequence.swift

+6-3
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
//
1010
//===----------------------------------------------------------------------===//
1111

12+
@available(AsyncAlgorithms 1.0, *)
1213
extension AsyncSequence {
1314
/// Creates an asynchronous sequence that creates chunks of a given `RangeReplaceableCollection` of a given count.
15+
@available(AsyncAlgorithms 1.0, *)
1416
@inlinable
1517
public func chunks<Collected: RangeReplaceableCollection>(
1618
ofCount count: Int,
@@ -20,13 +22,15 @@ extension AsyncSequence {
2022
}
2123

2224
/// Creates an asynchronous sequence that creates chunks of a given count.
25+
@available(AsyncAlgorithms 1.0, *)
2326
@inlinable
2427
public func chunks(ofCount count: Int) -> AsyncChunksOfCountSequence<Self, [Element]> {
2528
chunks(ofCount: count, into: [Element].self)
2629
}
2730
}
2831

2932
/// An `AsyncSequence` that chunks elements into `RangeReplaceableCollection` instances of at least a given count.
33+
@available(AsyncAlgorithms 1.0, *)
3034
public struct AsyncChunksOfCountSequence<Base: AsyncSequence, Collected: RangeReplaceableCollection>: AsyncSequence
3135
where Collected.Element == Base.Element {
3236
public typealias Element = Collected
@@ -89,8 +93,7 @@ where Collected.Element == Base.Element {
8993
}
9094
}
9195

96+
@available(AsyncAlgorithms 1.0, *)
9297
extension AsyncChunksOfCountSequence: Sendable where Base: Sendable, Base.Element: Sendable {}
98+
@available(AsyncAlgorithms 1.0, *)
9399
extension AsyncChunksOfCountSequence.Iterator: Sendable where Base.AsyncIterator: Sendable, Base.Element: Sendable {}
94-
95-
@available(*, unavailable)
96-
extension AsyncChunksOfCountSequence.Iterator: Sendable {}

Sources/AsyncAlgorithms/AsyncCompactedSequence.swift

+4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
//
1010
//===----------------------------------------------------------------------===//
1111

12+
@available(AsyncAlgorithms 1.0, *)
1213
extension AsyncSequence {
1314
/// Returns a new `AsyncSequence` that iterates over every non-nil element from the
1415
/// original `AsyncSequence`.
@@ -18,6 +19,7 @@ extension AsyncSequence {
1819
/// - Returns: An `AsyncSequence` where the element is the unwrapped original
1920
/// element and iterates over every non-nil element from the original
2021
/// `AsyncSequence`.
22+
@available(AsyncAlgorithms 1.0, *)
2123
@inlinable
2224
public func compacted<Unwrapped>() -> AsyncCompactedSequence<Self, Unwrapped>
2325
where Element == Unwrapped? {
@@ -27,6 +29,7 @@ extension AsyncSequence {
2729

2830
/// An `AsyncSequence` that iterates over every non-nil element from the original
2931
/// `AsyncSequence`.
32+
@available(AsyncAlgorithms 1.0, *)
3033
@frozen
3134
public struct AsyncCompactedSequence<Base: AsyncSequence, Element>: AsyncSequence
3235
where Base.Element == Element? {
@@ -66,6 +69,7 @@ where Base.Element == Element? {
6669
}
6770
}
6871

72+
@available(AsyncAlgorithms 1.0, *)
6973
extension AsyncCompactedSequence: Sendable where Base: Sendable, Base.Element: Sendable {}
7074

7175
@available(*, unavailable)

0 commit comments

Comments
 (0)