Skip to content

Commit 9a52d94

Browse files
committed
More extensive workaround
1 parent 9846ae6 commit 9a52d94

File tree

6 files changed

+60
-8
lines changed

6 files changed

+60
-8
lines changed

Sources/Testing/Expectations/ExpectationChecking+Macro.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
// See https://swift.org/CONTRIBUTORS.txt for Swift project authors
99
//
1010

11+
private import _TestingInternals
12+
1113
/// Check that an expectation has passed after a condition has been evaluated
1214
/// and throw an error if it failed.
1315
///
@@ -1199,6 +1201,31 @@ public func __checkClosureCall<each T>(
11991201
sourceLocation: sourceLocation
12001202
)
12011203
}
1204+
1205+
/// Check that an expression always exits (terminates the current process) with
1206+
/// a given status.
1207+
///
1208+
/// This overload is used for `await #expect(processExitsWith:) { }` invocations
1209+
/// that attempt to capture a non-`Sendable` or non-`Codable` value.
1210+
///
1211+
/// - Warning: This function is used to implement the `#expect()` and
1212+
/// `#require()` macros. Do not call it directly.
1213+
@_spi(Experimental)
1214+
@_disfavoredOverload
1215+
public func __checkClosureCall<each T>(
1216+
identifiedBy exitTestID: (UInt64, UInt64, UInt64, UInt64),
1217+
encodingCapturedValues capturedValues: (repeat each T),
1218+
processExitsWith expectedExitCondition: ExitTest.Condition,
1219+
observing observedValues: [any PartialKeyPath<ExitTest.Result> & Sendable] = [],
1220+
performing _: @convention(c) () -> Void,
1221+
expression: __Expression,
1222+
comments: @autoclosure () -> [Comment],
1223+
isRequired: Bool,
1224+
isolation: isolated (any Actor)? = #isolation,
1225+
sourceLocation: SourceLocation
1226+
) async -> Result<ExitTest.Result?, any Error> {
1227+
swt_unreachable()
1228+
}
12021229
#endif
12031230

12041231
// MARK: -

Sources/TestingMacros/ConditionMacro.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -441,9 +441,9 @@ extension ExitTestConditionMacro {
441441
// early if found.
442442
guard _diagnoseIssues(with: macro, body: bodyArgumentExpr, in: context) else {
443443
if Self.isThrowing {
444-
return #"{ () async throws -> Testing.ExitTest.Result in \#(ExprSyntax.unreachable) }()"#
444+
return .unreachable(as: "Testing.ExitTest.Result", withEffectKeywords: [.async, .throws])
445445
} else {
446-
return #"{ () async -> Testing.ExitTest.Result in \#(ExprSyntax.unreachable) }()"#
446+
return .unreachable(as: "Testing.ExitTest.Result", withEffectKeywords: [.async])
447447
}
448448
}
449449

Sources/TestingMacros/ExitTestCapturedValueMacro.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,11 @@ public struct ExitTestBadCapturedValueMacro: ExpressionMacro, Sendable {
5050
// Diagnose that the type of 'expr' is invalid.
5151
context.diagnose(.capturedValueMustBeSendableAndCodable(expr, name: nameExpr))
5252

53-
return .unreachable
53+
var type: TypeSyntax?
54+
if let typeExpr = arguments[2].expression.as(MemberAccessExprSyntax.self)?.base?.as(TupleExprSyntax.self)?.elements.first?.expression {
55+
type = "\(typeExpr.trimmed)"
56+
}
57+
return .unreachable(as: type)
5458
}
5559
}
5660

Sources/TestingMacros/Support/Additions/FunctionDeclSyntaxAdditions.swift

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,11 +182,32 @@ extension FunctionParameterSyntax {
182182
// MARK: -
183183

184184
extension ExprSyntax {
185-
/// An expression representing an unreachable code path.
185+
/// Get an expression representing an unreachable code path.
186+
///
187+
/// - Parameters:
188+
/// - type: The type to infer for the resulting expression. If `nil`, no
189+
/// type (other than `Swift.Never`) is inferred.
190+
/// - effectKeywords: Zero or more effect keywords to apply to the
191+
/// expression (e.g. `throws` if the expression should be treated as
192+
/// throwing.)
186193
///
187194
/// Use this expression when a macro will emit an error diagnostic but the
188195
/// compiler still requires us to produce a valid expression.
189-
static var unreachable: Self {
190-
#"Swift.fatalError("Unreachable")"#
196+
static func unreachable(as type: TypeSyntax? = nil, withEffectKeywords effectKeywords: [Keyword] = []) -> Self {
197+
let returnClause = type.map { type in
198+
ReturnClauseSyntax(
199+
leadingTrivia: .space,
200+
arrow: .arrowToken(trailingTrivia: .space),
201+
type: type.trimmed
202+
)
203+
}
204+
var effectSpecifiers = TypeEffectSpecifiersSyntax(throwsClause: nil)
205+
if effectKeywords.contains(.async) {
206+
effectSpecifiers.asyncSpecifier = .keyword(.async)
207+
}
208+
if effectKeywords.contains(.throws) {
209+
effectSpecifiers.throwsClause = ThrowsClauseSyntax(throwsSpecifier: .keyword(.throws))
210+
}
211+
return #"{ () \#(effectSpecifiers) \#(returnClause) in Swift.fatalError("Unreachable") }()"#
191212
}
192213
}

Sources/TestingMacros/Support/ClosureCaptureListParsing.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ struct CapturedValueInfo {
4141

4242
init(_ capture: ClosureCaptureSyntax, in context: some MacroExpansionContext) {
4343
self.capture = capture
44-
self.expression = .unreachable
44+
self.expression = .unreachable()
4545
self.type = "Swift.Never"
4646

4747
// We don't support capture specifiers at this time.

Sources/TestingMacros/TagMacro.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public struct TagMacro: PeerMacro, AccessorMacro, Sendable {
2222
/// This property is used rather than simply returning the empty array in
2323
/// order to suppress a compiler diagnostic about not producing any accessors.
2424
private static var _fallbackAccessorDecls: [AccessorDeclSyntax] {
25-
[#"get { \#(ExprSyntax.unreachable) }"#]
25+
[#"get { \#(ExprSyntax.unreachable()) }"#]
2626
}
2727

2828
public static func expansion(

0 commit comments

Comments
 (0)