|
5 | 5 |
|
6 | 6 | ## Swift 5.9
|
7 | 7 |
|
| 8 | +* [SE-0382][], [SE-0389][], [SE-0394][], [SE-0397][]: |
| 9 | + |
| 10 | + Swift 5.9 includes a new macro system that can be used to eliminate boilerplate and provide new forms of expressive APIs. Macros are declared with the new `macro` introducer: |
| 11 | + |
| 12 | + ```swift |
| 13 | + @freestanding(expression) |
| 14 | + macro assert(_ condition: Bool) = #externalMacro(module: "PowerAssertMacros", type: "AssertMacro") |
| 15 | + ``` |
| 16 | + |
| 17 | + Macros have parameter and result types, like functions, but are defined as separate programs that operate on syntax trees (using [swift-syntax][]) and produce new syntax trees that are incorporated into the program. Freestanding macros, indicated with the `@freestanding` attribute, are expanded in source code with a leading `#`: |
| 18 | + |
| 19 | + ```swift |
| 20 | + #assert(x + y == z) // expands to check the result of x + y == z and report failure if it's false |
| 21 | + ``` |
| 22 | + |
| 23 | + Macros can also be marked as `@attached`, in which case they will be meaning that they will be expanded using custom attribute syntax. For example: |
| 24 | + |
| 25 | + ```swift |
| 26 | + @attached(peer, names: overloaded) |
| 27 | + macro AddCompletionHandler() = #externalMacro( |
| 28 | + module: "ConcurrencyHelperMacros", |
| 29 | + type: "AddCompletionHandlerMacro" |
| 30 | + ) |
| 31 | + |
| 32 | + @AddCompletionHandler |
| 33 | + func fetchAvatar(from url: URL) throws -> Image { ... } |
| 34 | + |
| 35 | + // expands to... |
| 36 | + func fetchAvatar(from url: URL, completionHandler: @escaping (Result<Image, Error>) -> Void) { |
| 37 | + Task.detached { |
| 38 | + do { |
| 39 | + let result = try await fetchAvatar(from: url) |
| 40 | + completionHandler(.success(result)) |
| 41 | + } catch { |
| 42 | + completionHandler(.failure(error)) |
| 43 | + } |
| 44 | + } |
| 45 | + } |
| 46 | + ``` |
| 47 | + |
| 48 | + Macros are implemented in separate programs, which are executed by the Swift compiler. The Swift Package Manager's manifest provides a new `macro` target type to describe macros: |
| 49 | + |
| 50 | + ```swift |
| 51 | + import PackageDescription |
| 52 | + import CompilerPluginSupport |
| 53 | + |
| 54 | + let package = Package( |
| 55 | + name: "ConcurrencyHelpers", |
| 56 | + dependencies: [ |
| 57 | + .package(url: "https://github.com/apple/swift-syntax", from: "509.0.0"), |
| 58 | + ], |
| 59 | + targets: [ |
| 60 | + .macro(name: "ConcurrencyHelperMacros", |
| 61 | + dependencies: [ |
| 62 | + .product(name: "SwiftSyntaxMacros", package: "swift-syntax"), |
| 63 | + .product(name: "SwiftCompilerPlugin", package: "swift-syntax") |
| 64 | + ]), |
| 65 | + .target(name: "ConcurrencyHelpers", dependencies: ["ConcurrencyHelperMacros"]), |
| 66 | + .testTarget(name: "ConcurrencyHelperMacroTests", dependencies: ["ConcurrencyHelperMacros"]), |
| 67 | + ] |
| 68 | + ) |
| 69 | + ``` |
| 70 | + |
8 | 71 | * [SE-0380][]:
|
9 | 72 |
|
10 | 73 | `if` and `switch` statements may now be used as expressions to:
|
@@ -9766,7 +9829,10 @@ using the `.dynamicType` member to retrieve the type of an expression should mig
|
9766 | 9829 | [SE-0376]: <https://github.com/apple/swift-evolution/blob/main/proposals/0376-function-back-deployment.md>
|
9767 | 9830 | [SE-0377]: <https://github.com/apple/swift-evolution/blob/main/proposals/0377-parameter-ownership-modifiers.md>
|
9768 | 9831 | [SE-0380]: <https://github.com/apple/swift-evolution/blob/main/proposals/0380-if-switch-expressions.md>
|
9769 |
| - |
| 9832 | +[SE-0382]: https://github.com/apple/swift-evolution/blob/main/proposals/0382-expression-macros.md |
| 9833 | +[SE-0389]: https://github.com/apple/swift-evolution/blob/main/proposals/0389-attached-macros.md |
| 9834 | +[SE-0394]: https://github.com/apple/swift-evolution/blob/main/proposals/0394-swiftpm-expression-macros.md |
| 9835 | +[SE-0397]: https://github.com/apple/swift-evolution/blob/main/proposals/0397-freestanding-declaration-macros.md |
9770 | 9836 | [#64927]: <https://github.com/apple/swift/issues/64927>
|
9771 | 9837 | [#42697]: <https://github.com/apple/swift/issues/42697>
|
9772 | 9838 | [#42728]: <https://github.com/apple/swift/issues/42728>
|
@@ -9808,3 +9874,4 @@ using the `.dynamicType` member to retrieve the type of an expression should mig
|
9808 | 9874 | [#57081]: <https://github.com/apple/swift/issues/57081>
|
9809 | 9875 | [#57225]: <https://github.com/apple/swift/issues/57225>
|
9810 | 9876 | [#56139]: <https://github.com/apple/swift/issues/56139>
|
| 9877 | +[swift-syntax]: https://github.com/apple/swift-syntax |
0 commit comments