Skip to content

Commit 042e1c4

Browse files
authored
Move platform requirements to availability annotations (#348)
* 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. * Address naming feedback
1 parent 57b0814 commit 042e1c4

File tree

56 files changed

+225
-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

+225
-13
lines changed

Package.swift

+35-10
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,40 @@
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 initialIntroduction = "macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0"
14+
case pending = "macOS 9999, iOS 9999, tvOS 9999, watchOS 9999"
15+
// Use 10000 for future availability to avoid compiler magic around
16+
// the 9999 version number but ensure it is greater than 9999
17+
case future = "macOS 10000, iOS 10000, tvOS 10000, watchOS 10000"
18+
}
19+
20+
struct Availability {
21+
let name: String
22+
let osAvailability: OSAvailability
23+
24+
init(_ name: String, availability: OSAvailability = .initialIntroduction) {
25+
self.name = name
26+
self.osAvailability = availability
27+
}
28+
}
29+
30+
let availabilityMacros: [SwiftSetting] = versionNumbers.flatMap { version in
31+
availabilityTags.map {
32+
.enableExperimentalFeature("AvailabilityMacro=\($0.name) \(version):\($0.osAvailability.rawValue)")
33+
}
34+
}
435

536
let package = Package(
637
name: "swift-async-algorithms",
7-
platforms: [
8-
.macOS("10.15"),
9-
.iOS("13.0"),
10-
.tvOS("13.0"),
11-
.watchOS("6.0"),
12-
],
1338
products: [
1439
.library(name: "AsyncAlgorithms", targets: ["AsyncAlgorithms"])
1540
],
@@ -20,29 +45,29 @@ let package = Package(
2045
.product(name: "OrderedCollections", package: "swift-collections"),
2146
.product(name: "DequeModule", package: "swift-collections"),
2247
],
23-
swiftSettings: [
48+
swiftSettings: availabilityMacros + [
2449
.enableExperimentalFeature("StrictConcurrency=complete")
2550
]
2651
),
2752
.target(
2853
name: "AsyncSequenceValidation",
2954
dependencies: ["_CAsyncSequenceValidationSupport", "AsyncAlgorithms"],
30-
swiftSettings: [
55+
swiftSettings: availabilityMacros + [
3156
.enableExperimentalFeature("StrictConcurrency=complete")
3257
]
3358
),
3459
.systemLibrary(name: "_CAsyncSequenceValidationSupport"),
3560
.target(
3661
name: "AsyncAlgorithms_XCTest",
3762
dependencies: ["AsyncAlgorithms", "AsyncSequenceValidation"],
38-
swiftSettings: [
63+
swiftSettings: availabilityMacros + [
3964
.enableExperimentalFeature("StrictConcurrency=complete")
4065
]
4166
),
4267
.testTarget(
4368
name: "AsyncAlgorithmsTests",
4469
dependencies: ["AsyncAlgorithms", "AsyncSequenceValidation", "AsyncAlgorithms_XCTest"],
45-
swiftSettings: [
70+
swiftSettings: availabilityMacros + [
4671
.enableExperimentalFeature("StrictConcurrency=complete")
4772
]
4873
),

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 {}

0 commit comments

Comments
 (0)