Skip to content

Commit b82f95b

Browse files
committed
[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 f21d029 commit b82f95b

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
@@ -5577,6 +5577,18 @@ namespace {
55775577
E->setMacroRef(macroRef);
55785578
E->setType(expandedType);
55795579

5580+
auto fnType =
5581+
simplifyType(overload.adjustedOpenedType)->castTo<FunctionType>();
5582+
5583+
auto newArgs = coerceCallArguments(
5584+
E->getArgs(), fnType, macroRef, /*applyExpr=*/nullptr,
5585+
cs.getConstraintLocator(E, ConstraintLocator::ApplyArgument),
5586+
solution.getAppliedPropertyWrappers(E));
5587+
if (!newArgs)
5588+
return nullptr;
5589+
5590+
E->setArgs(newArgs);
5591+
55805592
// FIXME: Expansion should be lazy.
55815593
// i.e. 'ExpandMacroExpansionExprRequest' should be sinked into
55825594
// '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
@@ -659,6 +659,28 @@ func testLocalAccessorMacroWithAutoclosure() {
659659
takesAutoclosure(1)
660660
}
661661

662+
@propertyWrapper
663+
struct SomePropertyWrapper<T> {
664+
var wrappedValue: T
665+
init(wrappedValue: T) {
666+
self.wrappedValue = wrappedValue
667+
}
668+
init(projectedValue: Self) {
669+
self = projectedValue
670+
}
671+
var projectedValue: Self { self }
672+
}
673+
674+
// Property wrappers on macros probably aren't all that useful, but make sure
675+
// we don't crash.
676+
@freestanding(expression)
677+
macro hasPropertyWrapperParam(@SomePropertyWrapper x: Int) = #externalMacro(module: "MacroDefinition", type: "GenericToVoidMacro")
678+
679+
func testPropertyWrapperMacro() {
680+
#hasPropertyWrapperParam(x: 0)
681+
#hasPropertyWrapperParam($x: .init(wrappedValue: 0))
682+
}
683+
662684
#if TEST_DIAGNOSTICS
663685
@freestanding(expression)
664686
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)