Skip to content

Commit 8e154a4

Browse files
authored
Merge pull request swiftlang#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.

0 commit comments

Comments
 (0)