From 211118a7386141ca84661fcfc85d2a781d181e2e Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Tue, 24 Jun 2025 15:59:55 -0400 Subject: [PATCH 1/3] Work around a compiler regression affecting exit test value capturing. This PR works around a compiler regression as of Swift acbdfef4f4d71b1 that causes our helper macro `#__capturedValue()` to be incorrectly expanded (wrong overload is selected.) The workaround is to disable our use of this macro, which does not affect correct functioning of our code but which does degrade the quality of our diagnostics. Works around rdar://154221449. --- Sources/TestingMacros/Support/ClosureCaptureListParsing.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Sources/TestingMacros/Support/ClosureCaptureListParsing.swift b/Sources/TestingMacros/Support/ClosureCaptureListParsing.swift index 80c216854..c8eaa4729 100644 --- a/Sources/TestingMacros/Support/ClosureCaptureListParsing.swift +++ b/Sources/TestingMacros/Support/ClosureCaptureListParsing.swift @@ -36,7 +36,11 @@ struct CapturedValueInfo { /// The expression to assign to the captured value with type-checking applied. var typeCheckedExpression: ExprSyntax { +#if SWT_FIXED_154221449 #"#__capturedValue(\#(expression.trimmed), \#(literal: name.trimmedDescription), (\#(type.trimmed)).self)"# +#else + expression.trimmed +#endif } init(_ capture: ClosureCaptureSyntax, in context: some MacroExpansionContext) { From ec960353690003c48001d1039ab3cf76e0068341 Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Tue, 24 Jun 2025 19:11:27 -0400 Subject: [PATCH 2/3] Try a more extensive workaround until https://github.com/swiftlang/swift/pull/82467 lands --- .../ExpectationChecking+Macro.swift | 27 +++++++++++++++++++ Sources/TestingMacros/ConditionMacro.swift | 20 ++++++++++++++ .../Support/ClosureCaptureListParsing.swift | 6 +---- 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/Sources/Testing/Expectations/ExpectationChecking+Macro.swift b/Sources/Testing/Expectations/ExpectationChecking+Macro.swift index 3a190e679..9dfc5ace7 100644 --- a/Sources/Testing/Expectations/ExpectationChecking+Macro.swift +++ b/Sources/Testing/Expectations/ExpectationChecking+Macro.swift @@ -1175,6 +1175,7 @@ public func __checkClosureCall( /// /// - Warning: This function is used to implement the `#expect()` and /// `#require()` macros. Do not call it directly. +#if SWT_FIXED_154221449 @_spi(Experimental) public func __checkClosureCall( identifiedBy exitTestID: (UInt64, UInt64, UInt64, UInt64), @@ -1199,6 +1200,32 @@ public func __checkClosureCall( sourceLocation: sourceLocation ) } +#else +@_spi(Experimental) +public func __checkClosureCall( + identifiedBy exitTestID: (UInt64, UInt64, UInt64, UInt64), + encodingCapturedValues capturedValues: repeat each T, + processExitsWith expectedExitCondition: ExitTest.Condition, + observing observedValues: [any PartialKeyPath & Sendable] = [], + performing _: @convention(c) () -> Void, + expression: __Expression, + comments: @autoclosure () -> [Comment], + isRequired: Bool, + isolation: isolated (any Actor)? = #isolation, + sourceLocation: SourceLocation +) async -> Result where repeat each T: Codable & Sendable { + await callExitTest( + identifiedBy: exitTestID, + encodingCapturedValues: Array(repeat each capturedValues), + processExitsWith: expectedExitCondition, + observing: observedValues, + expression: expression, + comments: comments(), + isRequired: isRequired, + sourceLocation: sourceLocation + ) +} +#endif #endif // MARK: - diff --git a/Sources/TestingMacros/ConditionMacro.swift b/Sources/TestingMacros/ConditionMacro.swift index 0ef0970e9..e7a19cbc5 100644 --- a/Sources/TestingMacros/ConditionMacro.swift +++ b/Sources/TestingMacros/ConditionMacro.swift @@ -98,7 +98,13 @@ extension ConditionMacro { if let trailingClosureIndex { // Assume that the comment, if present is the last argument in the // argument list prior to the trailing closure that has no label. +#if SWT_FIXED_154221449 commentIndex = macroArguments[.. 1 { // If there is no trailing closure argument and there is more than one // argument, then the comment is the last argument with no label (and also @@ -547,6 +553,7 @@ extension ExitTestConditionMacro { var leadingArguments = [ Argument(label: "identifiedBy", expression: idExpr), ] +#if SWT_FIXED_154221449 if !capturedValues.isEmpty { leadingArguments.append( Argument( @@ -559,6 +566,19 @@ extension ExitTestConditionMacro { ) ) } +#else + if let firstCapturedValue = capturedValues.first { + leadingArguments.append( + Argument( + label: "encodingCapturedValues", + expression: firstCapturedValue.typeCheckedExpression + ) + ) + leadingArguments += capturedValues.dropFirst() + .map(\.typeCheckedExpression) + .map { Argument(expression: $0) } + } +#endif arguments = leadingArguments + arguments // Replace the exit test body (as an argument to the macro) with a stub diff --git a/Sources/TestingMacros/Support/ClosureCaptureListParsing.swift b/Sources/TestingMacros/Support/ClosureCaptureListParsing.swift index c8eaa4729..08536aa69 100644 --- a/Sources/TestingMacros/Support/ClosureCaptureListParsing.swift +++ b/Sources/TestingMacros/Support/ClosureCaptureListParsing.swift @@ -36,11 +36,7 @@ struct CapturedValueInfo { /// The expression to assign to the captured value with type-checking applied. var typeCheckedExpression: ExprSyntax { -#if SWT_FIXED_154221449 - #"#__capturedValue(\#(expression.trimmed), \#(literal: name.trimmedDescription), (\#(type.trimmed)).self)"# -#else - expression.trimmed -#endif + #"#__capturedValue(\#(expression.trimmed), \#(literal: name.trimmedDescription), \#(type.trimmed).self)"# } init(_ capture: ClosureCaptureSyntax, in context: some MacroExpansionContext) { From a4d20aaf5a574834ee329cb270df7f46f1f6335a Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Tue, 24 Jun 2025 20:32:27 -0400 Subject: [PATCH 3/3] Only special-case #__capturedValue in workaround code to avoid breaking e.g. #file --- Sources/TestingMacros/ConditionMacro.swift | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Sources/TestingMacros/ConditionMacro.swift b/Sources/TestingMacros/ConditionMacro.swift index e7a19cbc5..9d0c4f15f 100644 --- a/Sources/TestingMacros/ConditionMacro.swift +++ b/Sources/TestingMacros/ConditionMacro.swift @@ -102,7 +102,14 @@ extension ConditionMacro { commentIndex = macroArguments[.. 1 {