Skip to content

Commit 8e154a4

Browse files
authored
Merge pull request #39962 from lorentey/concurrency-availability
[stdlib] Introduce availability macros
2 parents 31e8933 + 4f7b9e1 commit 8e154a4

File tree

164 files changed

+786
-742
lines changed

Some content is hidden

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

164 files changed

+786
-742
lines changed

CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,18 @@ if(SWIFT_ENABLE_DISPATCH AND NOT CMAKE_SYSTEM_NAME STREQUAL Darwin)
525525
endif()
526526
endif()
527527

528+
set(SWIFT_STDLIB_AVAILABILITY_DEFINITIONS
529+
"SwiftStdlib 5.0:macOS 10.14.4, iOS 12.2, watchOS 5.2, tvOS 12.2"
530+
"SwiftStdlib 5.1:macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0"
531+
"SwiftStdlib 5.2:macOS 10.15.4, iOS 13.4, watchOS 6.2, tvOS 13.4"
532+
"SwiftStdlib 5.3:macOS 11.0, iOS 14.0, watchOS 7.0, tvOS 14.0"
533+
"SwiftStdlib 5.4:macOS 11.3, iOS 14.5, watchOS 7.4, tvOS 14.5"
534+
"SwiftStdlib 5.5:macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0"
535+
"SwiftStdlib 5.6:macOS 9999, iOS 9999, watchOS 9999, tvOS 9999"
536+
"SwiftStdlib 9999:macOS 9999, iOS 9999, watchOS 9999, tvOS 9999" # Unknown future release
537+
CACHE STRING
538+
"Availability macros for stdlib versions")
539+
528540
#
529541
# Include CMake modules
530542
#

docs/StandardLibraryProgrammersManual.md

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -298,34 +298,63 @@ Just like access control modifiers, we prefer to put `@available` attributes on
298298
299299
```swift
300300
// 😢👎
301-
@available(macOS 10.6, iOS 10, watchOS 3, tvOS 12, *)
301+
@available(SwiftStdlib 5.2, *)
302302
extension String {
303303
public func blanch() { ... }
304304
public func roast() { ... }
305305
}
306306
307307
// 🥲👍
308308
extension String {
309-
@available(macOS 10.6, iOS 10, watchOS 3, tvOS 12, *)
309+
@available(SwiftStdlib 5.2, *)
310310
public func blanch() { ... }
311311
312-
@available(macOS 10.6, iOS 10, watchOS 3, tvOS 12, *)
312+
@available(SwiftStdlib 5.2, *)
313313
public func roast() { ... }
314314
}
315315
```
316316
317317
This coding style is enforced by the ABI checker -- it will complain if an extension member declaration that needs an availability doesn't have it directly attached.
318318
319-
Features under development that haven't been released yet must be marked with the placeholder version number `9999`. This special version is always considered available in custom builds of the Swift toolchain (including development snapshots), but not in any ABI-stable production release.
319+
This repository defines a set of availability macros (of the form `SwiftStdlib x.y`) that map Swift Stdlib releases to the OS versions that shipped them, for all ABI stable platforms. The following two definitions are equivalent, but the second one is less error-prone, so we prefer that:
320320
321321
```swift
322+
extension String {
323+
// 😵‍💫👎
324+
@available(macOS 10.15.4, iOS 13.4, watchOS 6.2, tvOS 13.4, *)
325+
public func fiddle() { ... }
326+
327+
// 😎👍
328+
@available(SwiftStdlib 5.2, *)
329+
public func fiddle() { ... }
330+
}
331+
```
332+
333+
(Mistakes in the OS version number list are very easy to miss during review, but can have major ABI consequences.)
334+
335+
This is especially important for newly introduced APIs, where the corresponding OS releases may not even be known yet.
336+
337+
Features under development that haven't shipped yet must be marked as available in the placeholder OS version `9999`. This special version is always considered available in custom builds of the Swift toolchain (including development snapshots), but not in any ABI-stable production release.
338+
339+
Never explicitly spell out such placeholder availability -- instead, use the `SwiftStdlib` macro corresponding to the Swift version we're currently working on:
340+
341+
```swift
342+
// 😵‍💫👎
322343
@available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *)
323344
public struct FutureFeature {
324345
...
325346
}
347+
348+
// 😎👍
349+
@available(SwiftStdlib 6.3, *) // Or whatever
350+
public struct FutureFeature {
351+
...
352+
}
326353
```
327354
328-
On these platforms, the Swift Standard Library ships as an integrated part of the operating system; as such, it is the platform owners' responsibility to update these placeholder version numbers to actual versions as part of their release process.
355+
This way, platform owners can easily update declarations to the correct set of version numbers by simply changing the definition of the macro, rather than having to update each individual declaration.
356+
357+
If we haven't defined a version number for the "next" Swift release yet, please use the special placeholder version `SwiftStdlib 9999`, which always expands to 9999 versions. Declarations that use this version will need to be manually updated once we decide on the corresponding Swift version number.
329358
330359
## Internals
331360

lib/SILGen/SILGenFunction.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -927,7 +927,7 @@ void SILGenFunction::emitAsyncMainThreadStart(SILDeclRef entryPoint) {
927927
if (!getMainExecutorFuncDecl) {
928928
// If it doesn't exist due to an SDK-compiler mismatch, we can conjure one
929929
// up instead of crashing:
930-
// @available(SwiftStdlib 5.5, *)
930+
// @available(SwiftStdlib 5.1, *)
931931
// @_silgen_name("swift_task_getMainExecutor")
932932
// internal func _getMainExecutor() -> Builtin.Executor
933933

stdlib/cmake/modules/AddSwiftStdlib.cmake

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1722,6 +1722,11 @@ function(add_swift_target_library name)
17221722
"Either SHARED, STATIC, or OBJECT_LIBRARY must be specified")
17231723
endif()
17241724

1725+
# Define availability macros.
1726+
foreach(def ${SWIFT_STDLIB_AVAILABILITY_DEFINITIONS})
1727+
list(APPEND SWIFTLIB_SWIFT_COMPILE_FLAGS "-Xfrontend" "-define-availability" "-Xfrontend" "${def}")
1728+
endforeach()
1729+
17251730
# In the standard library and overlays, warn about implicit overrides
17261731
# as a reminder to consider when inherited protocols need different
17271732
# behavior for their requirements.

stdlib/private/StdlibUnittest/CMakeLists.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,6 @@ add_swift_target_library(swiftStdlibUnittest ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES}
5555
SWIFT_MODULE_DEPENDS_HAIKU Glibc
5656
SWIFT_MODULE_DEPENDS_WINDOWS CRT WinSDK
5757
SWIFT_COMPILE_FLAGS ${swift_stdlib_unittest_compile_flags} ${SWIFT_STANDARD_LIBRARY_SWIFT_FLAGS}
58-
-Xfrontend -define-availability
59-
-Xfrontend "SwiftStdlib 5.5:macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0"
6058
INSTALL_IN_COMPONENT stdlib-experimental
6159
DARWIN_INSTALL_NAME_DIR "${SWIFT_DARWIN_STDLIB_PRIVATE_INSTALL_NAME_DIR}"
6260
LINK_LIBRARIES ${swift_stdlib_unittest_link_libraries})

stdlib/private/StdlibUnittest/StdlibUnittest.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -880,7 +880,7 @@ func _childProcess() {
880880
}
881881

882882
#if SWIFT_ENABLE_EXPERIMENTAL_CONCURRENCY
883-
@available(SwiftStdlib 5.5, *)
883+
@available(SwiftStdlib 5.1, *)
884884
@inline(never)
885885
func _childProcessAsync() async {
886886
_installTrapInterceptor()
@@ -1375,7 +1375,7 @@ class _ParentProcess {
13751375
}
13761376

13771377
#if SWIFT_ENABLE_EXPERIMENTAL_CONCURRENCY
1378-
@available(SwiftStdlib 5.5, *)
1378+
@available(SwiftStdlib 5.1, *)
13791379
internal func runOneTestAsync(
13801380
fullTestName: String,
13811381
testSuite: TestSuite,
@@ -1542,7 +1542,7 @@ class _ParentProcess {
15421542
}
15431543

15441544
#if SWIFT_ENABLE_EXPERIMENTAL_CONCURRENCY
1545-
@available(SwiftStdlib 5.5, *)
1545+
@available(SwiftStdlib 5.1, *)
15461546
func runAsync() async {
15471547
if let filter = _filter {
15481548
print("StdlibUnittest: using filter: \(filter)")
@@ -1727,7 +1727,7 @@ public func runAllTests() {
17271727
}
17281728

17291729
#if SWIFT_ENABLE_EXPERIMENTAL_CONCURRENCY
1730-
@available(SwiftStdlib 5.5, *)
1730+
@available(SwiftStdlib 5.1, *)
17311731
public func runAllTestsAsync() async {
17321732
if PersistentState.runNoTestsWasCalled {
17331733
print("runAllTests() called after runNoTests(). Aborting.")
@@ -1915,7 +1915,7 @@ public final class TestSuite {
19151915
}
19161916

19171917
#if SWIFT_ENABLE_EXPERIMENTAL_CONCURRENCY
1918-
@available(SwiftStdlib 5.5, *)
1918+
@available(SwiftStdlib 5.1, *)
19191919
func _runTestAsync(name testName: String, parameter: Int?) async {
19201920
PersistentState.ranSomething = true
19211921
for r in _allResettables {

stdlib/public/Concurrency/Actor.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import Swift
1717
///
1818
/// The `Actor` protocol generalizes over all actor types. Actor types
1919
/// implicitly conform to this protocol.
20-
@available(SwiftStdlib 5.5, *)
20+
@available(SwiftStdlib 5.1, *)
2121
public protocol Actor: AnyObject, Sendable {
2222

2323
/// Retrieve the executor for this actor as an optimized, unowned
@@ -37,17 +37,17 @@ public protocol Actor: AnyObject, Sendable {
3737

3838
/// Called to initialize the default actor instance in an actor.
3939
/// The implementation will call this within the actor's initializer.
40-
@available(SwiftStdlib 5.5, *)
40+
@available(SwiftStdlib 5.1, *)
4141
@_silgen_name("swift_defaultActor_initialize")
4242
public func _defaultActorInitialize(_ actor: AnyObject)
4343

4444
/// Called to destroy the default actor instance in an actor.
4545
/// The implementation will call this within the actor's deinit.
46-
@available(SwiftStdlib 5.5, *)
46+
@available(SwiftStdlib 5.1, *)
4747
@_silgen_name("swift_defaultActor_destroy")
4848
public func _defaultActorDestroy(_ actor: AnyObject)
4949

50-
@available(SwiftStdlib 5.5, *)
50+
@available(SwiftStdlib 5.1, *)
5151
@_silgen_name("swift_task_enqueueMainExecutor")
5252
@usableFromInline
5353
internal func _enqueueOnMain(_ job: UnownedJob)

stdlib/public/Concurrency/AsyncCompactMapSequence.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
import Swift
1414

15-
@available(SwiftStdlib 5.5, *)
15+
@available(SwiftStdlib 5.1, *)
1616
extension AsyncSequence {
1717
/// Creates an asynchronous sequence that maps the given closure over the
1818
/// asynchronous sequence’s elements, omitting results that don't return a
@@ -55,7 +55,7 @@ extension AsyncSequence {
5555

5656
/// An asynchronous sequence that maps a given closure over the asynchronous
5757
/// sequence’s elements, omitting results that don't return a value.
58-
@available(SwiftStdlib 5.5, *)
58+
@available(SwiftStdlib 5.1, *)
5959
public struct AsyncCompactMapSequence<Base: AsyncSequence, ElementOfResult> {
6060
@usableFromInline
6161
let base: Base
@@ -73,7 +73,7 @@ public struct AsyncCompactMapSequence<Base: AsyncSequence, ElementOfResult> {
7373
}
7474
}
7575

76-
@available(SwiftStdlib 5.5, *)
76+
@available(SwiftStdlib 5.1, *)
7777
extension AsyncCompactMapSequence: AsyncSequence {
7878
/// The type of element produced by this asynchronous sequence.
7979
///

stdlib/public/Concurrency/AsyncDropFirstSequence.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
import Swift
1414

15-
@available(SwiftStdlib 5.5, *)
15+
@available(SwiftStdlib 5.1, *)
1616
extension AsyncSequence {
1717
/// Omits a specified number of elements from the base asynchronous sequence,
1818
/// then passes through all remaining elements.
@@ -48,7 +48,7 @@ extension AsyncSequence {
4848

4949
/// An asynchronous sequence which omits a specified number of elements from the
5050
/// base asynchronous sequence, then passes through all remaining elements.
51-
@available(SwiftStdlib 5.5, *)
51+
@available(SwiftStdlib 5.1, *)
5252
public struct AsyncDropFirstSequence<Base: AsyncSequence> {
5353
@usableFromInline
5454
let base: Base
@@ -63,7 +63,7 @@ public struct AsyncDropFirstSequence<Base: AsyncSequence> {
6363
}
6464
}
6565

66-
@available(SwiftStdlib 5.5, *)
66+
@available(SwiftStdlib 5.1, *)
6767
extension AsyncDropFirstSequence: AsyncSequence {
6868
/// The type of element produced by this asynchronous sequence.
6969
///
@@ -116,7 +116,7 @@ extension AsyncDropFirstSequence: AsyncSequence {
116116
}
117117
}
118118

119-
@available(SwiftStdlib 5.5, *)
119+
@available(SwiftStdlib 5.1, *)
120120
extension AsyncDropFirstSequence {
121121
/// Omits a specified number of elements from the base asynchronous sequence,
122122
/// then passes through all remaining elements.

stdlib/public/Concurrency/AsyncDropWhileSequence.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
import Swift
1414

15-
@available(SwiftStdlib 5.5, *)
15+
@available(SwiftStdlib 5.1, *)
1616
extension AsyncSequence {
1717
/// Omits elements from the base asynchronous sequence until a given closure
1818
/// returns false, after which it passes through all remaining elements.
@@ -52,7 +52,7 @@ extension AsyncSequence {
5252
/// An asynchronous sequence which omits elements from the base sequence until a
5353
/// given closure returns false, after which it passes through all remaining
5454
/// elements.
55-
@available(SwiftStdlib 5.5, *)
55+
@available(SwiftStdlib 5.1, *)
5656
public struct AsyncDropWhileSequence<Base: AsyncSequence> {
5757
@usableFromInline
5858
let base: Base
@@ -70,7 +70,7 @@ public struct AsyncDropWhileSequence<Base: AsyncSequence> {
7070
}
7171
}
7272

73-
@available(SwiftStdlib 5.5, *)
73+
@available(SwiftStdlib 5.1, *)
7474
extension AsyncDropWhileSequence: AsyncSequence {
7575

7676
/// The type of element produced by this asynchronous sequence.

stdlib/public/Concurrency/AsyncFilterSequence.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
import Swift
1414

15-
@available(SwiftStdlib 5.5, *)
15+
@available(SwiftStdlib 5.1, *)
1616
extension AsyncSequence {
1717
/// Creates an asynchronous sequence that contains, in order, the elements of
1818
/// the base sequence that satisfy the given predicate.
@@ -43,7 +43,7 @@ extension AsyncSequence {
4343

4444
/// An asynchronous sequence that contains, in order, the elements of
4545
/// the base sequence that satisfy a given predicate.
46-
@available(SwiftStdlib 5.5, *)
46+
@available(SwiftStdlib 5.1, *)
4747
public struct AsyncFilterSequence<Base: AsyncSequence> {
4848
@usableFromInline
4949
let base: Base
@@ -61,7 +61,7 @@ public struct AsyncFilterSequence<Base: AsyncSequence> {
6161
}
6262
}
6363

64-
@available(SwiftStdlib 5.5, *)
64+
@available(SwiftStdlib 5.1, *)
6565
extension AsyncFilterSequence: AsyncSequence {
6666
/// The type of element produced by this asynchronous sequence.
6767
///

stdlib/public/Concurrency/AsyncFlatMapSequence.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
import Swift
1414

15-
@available(SwiftStdlib 5.5, *)
15+
@available(SwiftStdlib 5.1, *)
1616
extension AsyncSequence {
1717
/// Creates an asynchronous sequence that concatenates the results of calling
1818
/// the given transformation with each element of this sequence.
@@ -49,7 +49,7 @@ extension AsyncSequence {
4949

5050
/// An asynchronous sequence that concatenates the results of calling a given
5151
/// transformation with each element of this sequence.
52-
@available(SwiftStdlib 5.5, *)
52+
@available(SwiftStdlib 5.1, *)
5353
public struct AsyncFlatMapSequence<Base: AsyncSequence, SegmentOfResult: AsyncSequence> {
5454
@usableFromInline
5555
let base: Base
@@ -67,7 +67,7 @@ public struct AsyncFlatMapSequence<Base: AsyncSequence, SegmentOfResult: AsyncSe
6767
}
6868
}
6969

70-
@available(SwiftStdlib 5.5, *)
70+
@available(SwiftStdlib 5.1, *)
7171
extension AsyncFlatMapSequence: AsyncSequence {
7272
/// The type of element produced by this asynchronous sequence.
7373
///

stdlib/public/Concurrency/AsyncIteratorProtocol.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ import Swift
8484
/// If the iterator needs to clean up on cancellation, it can do so after
8585
/// checking for cancellation as described above, or in `deinit` if it's
8686
/// a reference type.
87-
@available(SwiftStdlib 5.5, *)
87+
@available(SwiftStdlib 5.1, *)
8888
@rethrows
8989
public protocol AsyncIteratorProtocol {
9090
associatedtype Element

stdlib/public/Concurrency/AsyncLet.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import Swift
1616
// ==== Async Let -------------------------------------------------------------
1717
// Only has internal / builtin functions as it is not really accessible directly
1818

19-
@available(SwiftStdlib 5.5, *)
19+
@available(SwiftStdlib 5.1, *)
2020
@_silgen_name("swift_asyncLet_start")
2121
public func _asyncLetStart<T>(
2222
asyncLet: Builtin.RawPointer,
@@ -25,34 +25,34 @@ public func _asyncLetStart<T>(
2525
)
2626

2727
/// DEPRECATED. use _asyncLet_get instead
28-
@available(SwiftStdlib 5.5, *)
28+
@available(SwiftStdlib 5.1, *)
2929
@_silgen_name("swift_asyncLet_wait")
3030
public func _asyncLetGet<T>(asyncLet: Builtin.RawPointer) async -> T
3131

3232
/// DEPRECATED. use _asyncLet_get_throwing instead
33-
@available(SwiftStdlib 5.5, *)
33+
@available(SwiftStdlib 5.1, *)
3434
@_silgen_name("swift_asyncLet_wait_throwing")
3535
public func _asyncLetGetThrowing<T>(asyncLet: Builtin.RawPointer) async throws -> T
3636

3737
/// DEPRECATED. use _asyncLet_finish instead
38-
@available(SwiftStdlib 5.5, *)
38+
@available(SwiftStdlib 5.1, *)
3939
@_silgen_name("swift_asyncLet_end")
4040
public func _asyncLetEnd(
4141
asyncLet: Builtin.RawPointer // TODO: should this take __owned?
4242
)
4343

4444
/// Wait if necessary and then project the result value of an async let
45-
@available(SwiftStdlib 5.5, *)
45+
@available(SwiftStdlib 5.1, *)
4646
@_silgen_name("swift_asyncLet_get")
4747
public func _asyncLet_get(_ asyncLet: Builtin.RawPointer, _ resultBuffer: Builtin.RawPointer) async -> Builtin.RawPointer
4848

4949
/// Wait if necessary and then project the result value of an async let that throws
50-
@available(SwiftStdlib 5.5, *)
50+
@available(SwiftStdlib 5.1, *)
5151
@_silgen_name("swift_asyncLet_get_throwing")
5252
public func _asyncLet_get_throwing(_ asyncLet: Builtin.RawPointer, _ resultBuffer: Builtin.RawPointer) async throws -> Builtin.RawPointer
5353

5454
/// Wait if necessary and then tear down the async let task
55-
@available(SwiftStdlib 5.5, *)
55+
@available(SwiftStdlib 5.1, *)
5656
@_silgen_name("swift_asyncLet_finish")
5757
public func _asyncLet_finish(_ asyncLet: Builtin.RawPointer, _ resultBuffer: Builtin.RawPointer) async
5858

0 commit comments

Comments
 (0)