Skip to content

Commit 5674b6e

Browse files
authored
Merge pull request #80583 from hamishknight/macro-arg-apply
[CS] Make sure macro arguments go through `coerceCallArguments`
2 parents 3066570 + b82f95b commit 5674b6e

File tree

3 files changed

+92
-0
lines changed

3 files changed

+92
-0
lines changed

lib/Sema/CSApply.cpp

+12
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

+22
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

+58
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)