Skip to content

Commit b6a09d1

Browse files
committed
Reapply: [CS] Make sure macro arguments go through coerceCallArguments
Previously we would avoid rewriting the arguments in CSApply, but that can result in incorrect behavior in MiscDiagnostics passes, e.g incorrectly treating all closure arguments as escaping. Make sure we rewrite the arguments as we would in regular type-checking. rdar://148665502
1 parent aa2bb0c commit b6a09d1

File tree

3 files changed

+92
-0
lines changed

3 files changed

+92
-0
lines changed

lib/Sema/CSApply.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5612,6 +5612,18 @@ namespace {
56125612
E->setMacroRef(macroRef);
56135613
E->setType(expandedType);
56145614

5615+
auto fnType =
5616+
simplifyType(overload.adjustedOpenedType)->castTo<FunctionType>();
5617+
5618+
auto newArgs = coerceCallArguments(
5619+
E->getArgs(), fnType, macroRef, /*applyExpr=*/nullptr,
5620+
cs.getConstraintLocator(E, ConstraintLocator::ApplyArgument),
5621+
solution.getAppliedPropertyWrappers(E));
5622+
if (!newArgs)
5623+
return nullptr;
5624+
5625+
E->setArgs(newArgs);
5626+
56155627
// FIXME: Expansion should be lazy.
56165628
// i.e. 'ExpandMacroExpansionExprRequest' should be sinked into
56175629
// 'getRewritten()', and performed on-demand. Unfortunately that requires

test/Macros/macro_expand.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,28 @@ func testLocalAccessorMacroWithAutoclosure() {
667667
takesAutoclosure(1)
668668
}
669669

670+
@propertyWrapper
671+
struct SomePropertyWrapper<T> {
672+
var wrappedValue: T
673+
init(wrappedValue: T) {
674+
self.wrappedValue = wrappedValue
675+
}
676+
init(projectedValue: Self) {
677+
self = projectedValue
678+
}
679+
var projectedValue: Self { self }
680+
}
681+
682+
// Property wrappers on macros probably aren't all that useful, but make sure
683+
// we don't crash.
684+
@freestanding(expression)
685+
macro hasPropertyWrapperParam(@SomePropertyWrapper x: Int) = #externalMacro(module: "MacroDefinition", type: "GenericToVoidMacro")
686+
687+
func testPropertyWrapperMacro() {
688+
#hasPropertyWrapperParam(x: 0)
689+
#hasPropertyWrapperParam($x: .init(wrappedValue: 0))
690+
}
691+
670692
#if TEST_DIAGNOSTICS
671693
@freestanding(expression)
672694
macro missingMacro() = #externalMacro(module: "MacroDefinition", type: "BluhBlah")

test/Macros/macro_misc_diags.swift

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,32 @@ public struct TrailingClosureMacro: ExpressionMacro {
3636
}
3737
}
3838

39+
public struct CallClosureMacro: ExpressionMacro {
40+
public static func expansion(
41+
of macro: some FreestandingMacroExpansionSyntax,
42+
in context: some MacroExpansionContext
43+
) -> ExprSyntax {
44+
guard let argument = macro.trailingClosure else {
45+
fatalError()
46+
}
47+
return "\(argument)()"
48+
}
49+
}
50+
51+
public struct AddFunctionThatCallsClosureMacro: PeerMacro {
52+
public static func expansion(
53+
of node: AttributeSyntax,
54+
providingPeersOf declaration: some DeclSyntaxProtocol,
55+
in context: some MacroExpansionContext
56+
) throws -> [DeclSyntax] {
57+
guard case .argumentList(let args) = node.arguments else {
58+
fatalError()
59+
}
60+
let arg = args.first!
61+
return ["func qux() { \(arg)() }"]
62+
}
63+
}
64+
3965
public struct MakeBinding : DeclarationMacro {
4066
static public func expansion(
4167
of node: some FreestandingMacroExpansionSyntax,
@@ -64,6 +90,12 @@ macro identity<T>(_ x: T) -> T = #externalMacro(module: "MacroPlugin", type: "Id
6490
@freestanding(expression)
6591
macro trailingClosure<T>(_ x: T) -> T = #externalMacro(module: "MacroPlugin", type: "TrailingClosureMacro")
6692

93+
@freestanding(expression)
94+
macro takesNonEscapingClosure(_ x: () -> Void) = #externalMacro(module: "MacroPlugin", type: "CallClosureMacro")
95+
96+
@attached(peer, names: named(qux))
97+
macro AddFunctionThatCallsClosure<T>(_ fn: () -> T) = #externalMacro(module: "MacroPlugin", type: "AddFunctionThatCallsClosureMacro")
98+
6799
@freestanding(declaration, names: named(x))
68100
macro makeBinding<T>(_ x: T) = #externalMacro(module: "MacroPlugin", type: "MakeBinding")
69101

@@ -160,3 +192,29 @@ class rdar138997009_Class {
160192
}
161193
}
162194
}
195+
196+
// https://github.com/swiftlang/swift/issues/80561
197+
class TestNonEscaping {
198+
func foo() {}
199+
func bar() {
200+
_ = #takesNonEscapingClosure {
201+
foo()
202+
}
203+
_ = {
204+
_ = #takesNonEscapingClosure {
205+
foo()
206+
// CHECK-DIAG: @__swiftmacro_6Client0017Clientswift_yEEFcfMX[[@LINE-3]]{{.*}}takesNonEscapingClosurefMf_.swift:2:9: error: call to method 'foo' in closure requires explicit use of 'self' to make capture semantics explicit
207+
// CHECK-DIAG: Client.swift:[[@LINE-2]]:9: warning: call to method 'foo' in closure requires explicit use of 'self' to make capture semantics explicit; this will be an error in a future Swift language mode
208+
}
209+
}
210+
211+
@AddFunctionThatCallsClosure({ foo() })
212+
func baz() {}
213+
}
214+
func qux() {
215+
@AddFunctionThatCallsClosure({ _ = { foo() } })
216+
func baz() {}
217+
// CHECK-DIAG: Client.swift:[[@LINE-2]]:42: warning: call to method 'foo' in closure requires explicit use of 'self' to make capture semantics explicit; this will be an error in a future Swift language mode
218+
// CHECK-DIAG: @__swiftmacro_6Client15TestNonEscapingC3quxyyF7baz_$l{{.*}}AddFunctionThatCallsClosurefMp_.swift:4:13: error: call to method 'foo' in closure requires explicit use of 'self' to make capture semantics explicit
219+
}
220+
}

0 commit comments

Comments
 (0)