Skip to content

Commit a63c8d5

Browse files
authored
Merge pull request #66117 from DougGregor/se-0397-enable-by-default-5.9
[SE-0397] Enable freestanding declaration macros by default.
2 parents a6d79de + 43fb0a5 commit a63c8d5

File tree

13 files changed

+96
-34
lines changed

13 files changed

+96
-34
lines changed

CHANGELOG.md

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,69 @@ _**Note:** This is in reverse chronological order, so newer entries are added to
44

55
## Swift 5.9
66

7+
* [SE-0382][], [SE-0389][], [SE-0394][], [SE-0397][]:
8+
9+
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:
10+
11+
```swift
12+
@freestanding(expression)
13+
macro assert(_ condition: Bool) = #externalMacro(module: "PowerAssertMacros", type: "AssertMacro")
14+
```
15+
16+
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 `#`:
17+
18+
```swift
19+
#assert(x + y == z) // expands to check the result of x + y == z and report failure if it's false
20+
```
21+
22+
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:
23+
24+
```swift
25+
@attached(peer, names: overloaded)
26+
macro AddCompletionHandler() = #externalMacro(
27+
module: "ConcurrencyHelperMacros",
28+
type: "AddCompletionHandlerMacro"
29+
)
30+
31+
@AddCompletionHandler
32+
func fetchAvatar(from url: URL) throws -> Image { ... }
33+
34+
// expands to...
35+
func fetchAvatar(from url: URL, completionHandler: @escaping (Result<Image, Error>) -> Void) {
36+
Task.detached {
37+
do {
38+
let result = try await fetchAvatar(from: url)
39+
completionHandler(.success(result))
40+
} catch {
41+
completionHandler(.failure(error))
42+
}
43+
}
44+
}
45+
```
46+
47+
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:
48+
49+
```swift
50+
import PackageDescription
51+
import CompilerPluginSupport
52+
53+
let package = Package(
54+
name: "ConcurrencyHelpers",
55+
dependencies: [
56+
.package(url: "https://github.com/apple/swift-syntax", from: "509.0.0"),
57+
],
58+
targets: [
59+
.macro(name: "ConcurrencyHelperMacros",
60+
dependencies: [
61+
.product(name: "SwiftSyntaxMacros", package: "swift-syntax"),
62+
.product(name: "SwiftCompilerPlugin", package: "swift-syntax")
63+
]),
64+
.target(name: "ConcurrencyHelpers", dependencies: ["ConcurrencyHelperMacros"]),
65+
.testTarget(name: "ConcurrencyHelperMacroTests", dependencies: ["ConcurrencyHelperMacros"]),
66+
]
67+
)
68+
```
69+
770
* [SE-0380][]:
871

972
`if` and `switch` statements may now be used as expressions to:
@@ -9763,7 +9826,10 @@ using the `.dynamicType` member to retrieve the type of an expression should mig
97639826
[SE-0376]: <https://github.com/apple/swift-evolution/blob/main/proposals/0376-function-back-deployment.md>
97649827
[SE-0377]: <https://github.com/apple/swift-evolution/blob/main/proposals/0377-parameter-ownership-modifiers.md>
97659828
[SE-0380]: <https://github.com/apple/swift-evolution/blob/main/proposals/0380-if-switch-expressions.md>
9766-
9829+
[SE-0382]: https://github.com/apple/swift-evolution/blob/main/proposals/0382-expression-macros.md
9830+
[SE-0389]: https://github.com/apple/swift-evolution/blob/main/proposals/0389-attached-macros.md
9831+
[SE-0394]: https://github.com/apple/swift-evolution/blob/main/proposals/0394-swiftpm-expression-macros.md
9832+
[SE-0397]: https://github.com/apple/swift-evolution/blob/main/proposals/0397-freestanding-declaration-macros.md
97679833
[#64927]: <https://github.com/apple/swift/issues/64927>
97689834
[#42697]: <https://github.com/apple/swift/issues/42697>
97699835
[#42728]: <https://github.com/apple/swift/issues/42728>
@@ -9805,3 +9871,4 @@ using the `.dynamicType` member to retrieve the type of an expression should mig
98059871
[#57081]: <https://github.com/apple/swift/issues/57081>
98069872
[#57225]: <https://github.com/apple/swift/issues/57225>
98079873
[#56139]: <https://github.com/apple/swift/issues/56139>
9874+
[swift-syntax]: https://github.com/apple/swift-syntax

include/swift/Basic/Features.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ LANGUAGE_FEATURE(
106106
LANGUAGE_FEATURE(AttachedMacros, 389, "Attached macros", hasSwiftSwiftParser)
107107
LANGUAGE_FEATURE(MoveOnly, 390, "noncopyable types", true)
108108
LANGUAGE_FEATURE(ParameterPacks, 393, "Value and type parameter packs", true)
109+
LANGUAGE_FEATURE(FreestandingMacros, 397, "freestanding declaration macros", true)
109110

110111
UPCOMING_FEATURE(ConciseMagicFile, 274, 6)
111112
UPCOMING_FEATURE(ForwardTrailingClosures, 286, 6)
@@ -117,7 +118,6 @@ EXPERIMENTAL_FEATURE(StaticAssert, false)
117118
EXPERIMENTAL_FEATURE(VariadicGenerics, false)
118119
EXPERIMENTAL_FEATURE(NamedOpaqueTypes, false)
119120
EXPERIMENTAL_FEATURE(FlowSensitiveConcurrencyCaptures, false)
120-
EXPERIMENTAL_FEATURE(FreestandingMacros, true)
121121
EXPERIMENTAL_FEATURE(CodeItemMacros, true)
122122
EXPERIMENTAL_FEATURE(TupleConformances, false)
123123

lib/Sema/TypeCheckMacros.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -963,11 +963,6 @@ swift::expandFreestandingMacro(MacroExpansionDecl *med) {
963963
// macros need the `FreestandingMacros` feature flag, and code item macros
964964
// need both `FreestandingMacros` and `CodeItemMacros`.
965965
if (!macroRoles.contains(MacroRole::Expression)) {
966-
if (!ctx.LangOpts.hasFeature(Feature::FreestandingMacros)) {
967-
med->diagnose(diag::macro_experimental, "freestanding",
968-
"FreestandingMacros");
969-
return None;
970-
}
971966
if (!macroRoles.contains(MacroRole::Declaration) &&
972967
!ctx.LangOpts.hasFeature(Feature::CodeItemMacros)) {
973968
med->diagnose(diag::macro_experimental, "code item", "CodeItemMacros");

test/Macros/macro_expand.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,32 @@
44
// RUN: %host-build-swift -swift-version 5 -emit-library -o %t/%target-library-name(MacroDefinition) -module-name=MacroDefinition %S/Inputs/syntax_macro_definitions.swift -g -no-toolchain-stdlib-rpath -swift-version 5
55

66
// Diagnostics testing
7-
// RUN: %target-typecheck-verify-swift -swift-version 5 -enable-experimental-feature FreestandingMacros -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser -DTEST_DIAGNOSTICS
7+
// RUN: %target-typecheck-verify-swift -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser -DTEST_DIAGNOSTICS
88

99
// Diagnostics testing by importing macros from a module
1010
// RUN: %target-swift-frontend -swift-version 5 -emit-module -o %t/freestanding_macro_library.swiftmodule %S/Inputs/freestanding_macro_library.swift -module-name freestanding_macro_library -load-plugin-library %t/%target-library-name(MacroDefinition)
1111
// RUN: %target-swift-frontend -swift-version 5 -emit-module -o %t/freestanding_macro_library_2.swiftmodule %S/Inputs/freestanding_macro_library_2.swift -module-name freestanding_macro_library_2 -load-plugin-library %t/%target-library-name(MacroDefinition) -I %t
1212

13-
// RUN: %target-typecheck-verify-swift -swift-version 5 -enable-experimental-feature FreestandingMacros -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser -DTEST_DIAGNOSTICS -I %t -DIMPORT_MACRO_LIBRARY
13+
// RUN: %target-typecheck-verify-swift -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser -DTEST_DIAGNOSTICS -I %t -DIMPORT_MACRO_LIBRARY
1414

15-
// RUN: not %target-swift-frontend -swift-version 5 -typecheck -enable-experimental-feature FreestandingMacros -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser -DTEST_DIAGNOSTICS -serialize-diagnostics-path %t/macro_expand.dia %s -emit-macro-expansion-files no-diagnostics > %t/macro-printing.txt
15+
// RUN: not %target-swift-frontend -swift-version 5 -typecheck -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser -DTEST_DIAGNOSTICS -serialize-diagnostics-path %t/macro_expand.dia %s -emit-macro-expansion-files no-diagnostics > %t/macro-printing.txt
1616
// RUN: c-index-test -read-diagnostics %t/macro_expand.dia 2>&1 | %FileCheck -check-prefix CHECK-DIAGS %s
1717

1818
// RUN: %FileCheck %s --check-prefix CHECK-MACRO-PRINTED < %t/macro-printing.txt
1919

2020
// Debug info SIL testing
21-
// RUN: %target-swift-frontend -swift-version 5 -emit-sil -enable-experimental-feature FreestandingMacros -load-plugin-library %t/%target-library-name(MacroDefinition) %s -module-name MacroUser -o - -g | %FileCheck --check-prefix CHECK-SIL %s
21+
// RUN: %target-swift-frontend -swift-version 5 -emit-sil -load-plugin-library %t/%target-library-name(MacroDefinition) %s -module-name MacroUser -o - -g | %FileCheck --check-prefix CHECK-SIL %s
2222

2323
// Debug info IR testing
24-
// RUN: %target-swift-frontend -swift-version 5 -emit-ir -enable-experimental-feature FreestandingMacros -load-plugin-library %t/%target-library-name(MacroDefinition) %s -module-name MacroUser -o - -g | %FileCheck --check-prefix CHECK-IR %s
24+
// RUN: %target-swift-frontend -swift-version 5 -emit-ir -load-plugin-library %t/%target-library-name(MacroDefinition) %s -module-name MacroUser -o - -g | %FileCheck --check-prefix CHECK-IR %s
2525

2626
// Execution testing
27-
// RUN: %target-build-swift -swift-version 5 -g -enable-experimental-feature FreestandingMacros -load-plugin-library %t/%target-library-name(MacroDefinition) %s -o %t/main -module-name MacroUser
27+
// RUN: %target-build-swift -swift-version 5 -g -load-plugin-library %t/%target-library-name(MacroDefinition) %s -o %t/main -module-name MacroUser
2828
// RUN: %target-codesign %t/main
2929
// RUN: %target-run %t/main | %FileCheck %s
3030

3131
// Plugin search path and loaded module trace testing
32-
// RUN: %target-swift-frontend -swift-version 5 -emit-sil -enable-experimental-feature FreestandingMacros -plugin-path %t %s -module-name MacroUser -emit-loaded-module-trace -o %t/loaded_module_trace
32+
// RUN: %target-swift-frontend -swift-version 5 -emit-sil -plugin-path %t %s -module-name MacroUser -emit-loaded-module-trace -o %t/loaded_module_trace
3333
// RUN: %FileCheck -check-prefix=CHECK-MODULE-TRACE %s < %t/loaded_module_trace.trace.json
3434

3535
// CHECK-MODULE-TRACE: {{libMacroDefinition.dylib|libMacroDefinition.so|MacroDefinition.dll}}

test/Macros/macro_expand_closure.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99

1010
// Debug info SIL testing
11-
// RUN: %target-swift-frontend -swift-version 5 -emit-sil -enable-experimental-feature FreestandingMacros -load-plugin-library %t/%target-library-name(MacroDefinition) %s -module-name MacroUser -o - -g | %FileCheck --check-prefix CHECK-SIL %s
11+
// RUN: %target-swift-frontend -swift-version 5 -emit-sil -load-plugin-library %t/%target-library-name(MacroDefinition) %s -module-name MacroUser -o - -g | %FileCheck --check-prefix CHECK-SIL %s
1212

1313

1414
@freestanding(expression) public macro multiStatement() -> Int = #externalMacro(module: "MacroDefinition", type: "MultiStatementClosure")

test/Macros/macro_expand_codeitems.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
// RUN: %host-build-swift -swift-version 5 -emit-library -o %t/%target-library-name(MacroDefinition) -module-name=MacroDefinition %S/Inputs/syntax_macro_definitions.swift -g -no-toolchain-stdlib-rpath -swift-version 5
44

55
// Diagnostics testing
6-
// RUN: %target-typecheck-verify-swift -swift-version 5 -enable-experimental-feature FreestandingMacros -enable-experimental-feature CodeItemMacros -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser -DTEST_DIAGNOSTICS
7-
// RUN: %target-swift-frontend -swift-version 5 -emit-sil -enable-experimental-feature FreestandingMacros -enable-experimental-feature CodeItemMacros -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser -DTEST_DIAGNOSTICS -serialize-diagnostics-path %t/macro_expand_codeitems.dia %s -emit-macro-expansion-files no-diagnostics
6+
// RUN: %target-typecheck-verify-swift -swift-version 5 -enable-experimental-feature CodeItemMacros -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser -DTEST_DIAGNOSTICS
7+
// RUN: %target-swift-frontend -swift-version 5 -emit-sil -enable-experimental-feature CodeItemMacros -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser -DTEST_DIAGNOSTICS -serialize-diagnostics-path %t/macro_expand_codeitems.dia %s -emit-macro-expansion-files no-diagnostics
88
// RUN: c-index-test -read-diagnostics %t/macro_expand_codeitems.dia 2>&1 | %FileCheck -check-prefix CHECK-DIAGS %s
99

1010
// Execution testing
11-
// RUN: %target-build-swift -swift-version 5 -g -enable-experimental-feature FreestandingMacros -enable-experimental-feature CodeItemMacros -load-plugin-library %t/%target-library-name(MacroDefinition) %s -o %t/main -module-name MacroUser
11+
// RUN: %target-build-swift -swift-version 5 -g -enable-experimental-feature CodeItemMacros -load-plugin-library %t/%target-library-name(MacroDefinition) %s -o %t/main -module-name MacroUser
1212
// RUN: %target-codesign %t/main
1313
// RUN: %target-run %t/main | %FileCheck %s
1414

test/Macros/macro_expand_other.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
// RUN: %host-build-swift -swift-version 5 -emit-library -o %t/%target-library-name(MacroDefinition) -parse-as-library -module-name=MacroDefinition %S/Inputs/syntax_macro_definitions.swift -g -no-toolchain-stdlib-rpath
55

66
// Diagnostics testing
7-
// RUN: %target-typecheck-verify-swift -swift-version 5 -enable-experimental-feature FreestandingMacros -load-plugin-library %t/%target-library-name(MacroDefinition) -I %swift-host-lib-dir -module-name MacroUser -DTEST_DIAGNOSTICS
7+
// RUN: %target-typecheck-verify-swift -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -I %swift-host-lib-dir -module-name MacroUser -DTEST_DIAGNOSTICS
88

99
// Execution testing
10-
// RUN: %target-build-swift -swift-version 5 -enable-experimental-feature FreestandingMacros -load-plugin-library %t/%target-library-name(MacroDefinition) -I %swift-host-lib-dir -L %swift-host-lib-dir %s -o %t/main -module-name MacroUser
10+
// RUN: %target-build-swift -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -I %swift-host-lib-dir -L %swift-host-lib-dir %s -o %t/main -module-name MacroUser
1111
// RUN: %target-codesign %t/main
1212
// RUN: %target-run %t/main | %FileCheck %s
1313
// REQUIRES: swift_swift_parser, executable_test

test/Macros/macros_diagnostics.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// REQUIRES: swift_swift_parser
22

3-
// RUN: %target-typecheck-verify-swift -swift-version 5 -enable-experimental-feature FreestandingMacros -enable-experimental-feature CodeItemMacros -module-name MacrosTest
3+
// RUN: %target-typecheck-verify-swift -swift-version 5 -enable-experimental-feature CodeItemMacros -module-name MacrosTest
44

55
@expression macro stringify<T>(_ value: T) -> (T, String) = #externalMacro(module: "MacroDefinition", type: "StringifyMacro")
66
// expected-note@-1 2{{'stringify' declared here}}

test/Macros/macros_library_mode_diagnostics.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// REQUIRES: swift_swift_parser
22

3-
// RUN: %target-typecheck-verify-swift -swift-version 5 -enable-experimental-feature FreestandingMacros -parse-as-library -module-name MacrosTest
3+
// RUN: %target-typecheck-verify-swift -swift-version 5 -parse-as-library -module-name MacrosTest
44

55
// We need this test because top-level freestanding macro expansions are parsed
66
// differently in library mode.

test/Macros/parsing.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// REQUIRES: swift_swift_parser
22

3-
// RUN: %target-typecheck-verify-swift -swift-version 5 -enable-experimental-feature FreestandingMacros
3+
// RUN: %target-typecheck-verify-swift -swift-version 5
44

55
protocol P { }
66
protocol Q { associatedtype Assoc }

test/Macros/top_level_freestanding.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
// REQUIRES: swift_swift_parser, executable_test
22
//
33
// RUN: %empty-directory(%t)
4-
// RUN: %host-build-swift -swift-version 5 -parse-as-library -enable-experimental-feature FreestandingMacros -emit-library -o %t/%target-library-name(MacroDefinition) -module-name=MacroDefinition %S/Inputs/syntax_macro_definitions.swift -g -no-toolchain-stdlib-rpath
5-
// RUN: %target-swift-frontend -enable-experimental-feature FreestandingMacros -parse-as-library -emit-sil -load-plugin-library %t/%target-library-name(MacroDefinition) %s -module-name MacroUser 2>&1 | %FileCheck --check-prefix CHECK-SIL %s
4+
// RUN: %host-build-swift -swift-version 5 -parse-as-library -emit-library -o %t/%target-library-name(MacroDefinition) -module-name=MacroDefinition %S/Inputs/syntax_macro_definitions.swift -g -no-toolchain-stdlib-rpath
5+
// RUN: %target-swift-frontend -parse-as-library -emit-sil -load-plugin-library %t/%target-library-name(MacroDefinition) %s -module-name MacroUser 2>&1 | %FileCheck --check-prefix CHECK-SIL %s
66

77
// Type check testing
8-
// RUN: %target-typecheck-verify-swift -swift-version 5 -enable-experimental-feature FreestandingMacros -parse-as-library -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser -DTEST_DIAGNOSTICS -swift-version 5 %S/Inputs/top_level_freestanding_other.swift
8+
// RUN: %target-typecheck-verify-swift -swift-version 5 -parse-as-library -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser -DTEST_DIAGNOSTICS -swift-version 5 %S/Inputs/top_level_freestanding_other.swift
99

1010
// Type check testing with imported macro declarations
1111
// RUN: %target-swift-frontend -swift-version 5 -emit-module -o %t/freestanding_macro_library.swiftmodule %S/Inputs/freestanding_macro_library.swift -module-name freestanding_macro_library -load-plugin-library %t/%target-library-name(MacroDefinition)
1212

13-
// RUN: %target-typecheck-verify-swift -swift-version 5 -enable-experimental-feature FreestandingMacros -parse-as-library -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser -DTEST_DIAGNOSTICS -DIMPORT_MACRO_LIBRARY -swift-version 5 %S/Inputs/top_level_freestanding_other.swift -I %t
13+
// RUN: %target-typecheck-verify-swift -swift-version 5 -parse-as-library -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser -DTEST_DIAGNOSTICS -DIMPORT_MACRO_LIBRARY -swift-version 5 %S/Inputs/top_level_freestanding_other.swift -I %t
1414

1515
// Check diagnostic buffer names
16-
// RUN: %target-swift-frontend -typecheck -swift-version 5 -enable-experimental-feature FreestandingMacros -parse-as-library -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser -DTEST_DIAGNOSTICS -swift-version 5 %s %S/Inputs/top_level_freestanding_other.swift 2> %t.diags
16+
// RUN: %target-swift-frontend -typecheck -swift-version 5 -parse-as-library -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser -DTEST_DIAGNOSTICS -swift-version 5 %s %S/Inputs/top_level_freestanding_other.swift 2> %t.diags
1717
// RUN: %FileCheck -check-prefix DIAG_BUFFERS %s < %t.diags
1818

1919
// Execution testing
20-
// RUN: %target-build-swift -g -swift-version 5 -enable-experimental-feature FreestandingMacros -parse-as-library -load-plugin-library %t/%target-library-name(MacroDefinition) %s %S/Inputs/top_level_freestanding_other.swift -o %t/main -module-name MacroUser -swift-version 5
20+
// RUN: %target-build-swift -g -swift-version 5 -parse-as-library -load-plugin-library %t/%target-library-name(MacroDefinition) %s %S/Inputs/top_level_freestanding_other.swift -o %t/main -module-name MacroUser -swift-version 5
2121
// RUN: %target-codesign %t/main
2222
// RUN: %target-run %t/main | %FileCheck %s
2323

0 commit comments

Comments
 (0)