@@ -12,7 +12,7 @@ import SwiftSyntax
12
12
import SwiftSyntaxBuilder
13
13
import SwiftSyntaxMacros
14
14
15
- // MARK: - Finding effect keywords
15
+ // MARK: - Finding effect keywords and expressions
16
16
17
17
/// A syntax visitor class that looks for effectful keywords in a given
18
18
/// expression.
@@ -69,6 +69,21 @@ func findEffectKeywords(in node: some SyntaxProtocol, context: some MacroExpansi
69
69
return effectFinder. effectKeywords
70
70
}
71
71
72
+ extension BidirectionalCollection < Syntax > {
73
+ /// The suffix of syntax nodes in this collection which are effectful
74
+ /// expressions, such as those for `try` or `await`.
75
+ var trailingEffectExpressions : some Collection < Syntax > {
76
+ reversed ( )
77
+ . prefix { node in
78
+ // This could be simplified if/when swift-syntax introduces a protocol
79
+ // which all effectful expression syntax node types conform to.
80
+ // See https://github.com/swiftlang/swift-syntax/issues/3040
81
+ node. is ( TryExprSyntax . self) || node. is ( AwaitExprSyntax . self) || node. is ( UnsafeExprSyntax . self)
82
+ }
83
+ . reversed ( )
84
+ }
85
+ }
86
+
72
87
// MARK: - Inserting effect keywords/thunks
73
88
74
89
/// Make a function call expression to an effectful thunk function provided by
@@ -111,7 +126,13 @@ func applyEffectfulKeywords(_ effectfulKeywords: Set<Keyword>, to expr: some Exp
111
126
112
127
let needAwait = effectfulKeywords. contains ( . await ) && !expr. is ( AwaitExprSyntax . self)
113
128
let needTry = effectfulKeywords. contains ( . try ) && !expr. is ( TryExprSyntax . self)
129
+
130
+ // The 'unsafe' keyword was introduced in 6.2 as part of SE-0458. Older
131
+ // toolchains are not aware of it, so avoid emitting expressions involving
132
+ // that keyword when the macro has been built using an older toolchain.
133
+ #if compiler(>=6.2)
114
134
let needUnsafe = effectfulKeywords. contains ( . unsafe) && !expr. is ( UnsafeExprSyntax . self)
135
+ #endif
115
136
116
137
// First, add thunk function calls.
117
138
if needAwait {
@@ -120,9 +141,11 @@ func applyEffectfulKeywords(_ effectfulKeywords: Set<Keyword>, to expr: some Exp
120
141
if needTry {
121
142
expr = _makeCallToEffectfulThunk ( . identifier( " __requiringTry " ) , passing: expr)
122
143
}
144
+ #if compiler(>=6.2)
123
145
if needUnsafe {
124
146
expr = _makeCallToEffectfulThunk ( . identifier( " __requiringUnsafe " ) , passing: expr)
125
147
}
148
+ #endif
126
149
127
150
// Then add keyword expressions. (We do this separately so we end up writing
128
151
// `try await __r(__r(self))` instead of `try __r(await __r(self))` which is
@@ -143,6 +166,7 @@ func applyEffectfulKeywords(_ effectfulKeywords: Set<Keyword>, to expr: some Exp
143
166
)
144
167
)
145
168
}
169
+ #if compiler(>=6.2)
146
170
if needUnsafe {
147
171
expr = ExprSyntax (
148
172
UnsafeExprSyntax (
@@ -151,6 +175,7 @@ func applyEffectfulKeywords(_ effectfulKeywords: Set<Keyword>, to expr: some Exp
151
175
)
152
176
)
153
177
}
178
+ #endif
154
179
155
180
expr. leadingTrivia = originalExpr. leadingTrivia
156
181
expr. trailingTrivia = originalExpr. trailingTrivia
0 commit comments