Skip to content

Commit 9c3b8a6

Browse files
committed
[CS] Delay macro expansion until end of CSApply
Attempting to expand macros in the middle of CSApply can result in attempting to run MiscDiagnostics within a closure that hasn't yet had the solution applied to the AST, which can crash the implicit-self diagnostic logic. Move the expansion to the end of CSApply such that expansions are type-checked along with local decls, ensuring it's run after the solution has been applied to the AST. rdar://138997009
1 parent be94e5d commit 9c3b8a6

File tree

2 files changed

+45
-4
lines changed

2 files changed

+45
-4
lines changed

lib/Sema/CSApply.cpp

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,7 @@ namespace {
410410
class ExprRewriter : public ExprVisitor<ExprRewriter, Expr *> {
411411
// Delayed items to type-check.
412412
SmallVector<Decl *, 4> LocalDeclsToTypeCheck;
413+
SmallVector<MacroExpansionExpr *, 4> MacrosToExpand;
413414

414415
public:
415416
ConstraintSystem &cs;
@@ -431,6 +432,10 @@ namespace {
431432
LocalDeclsToTypeCheck.push_back(D);
432433
}
433434

435+
void addMacroToExpand(MacroExpansionExpr *E) {
436+
MacrosToExpand.push_back(E);
437+
}
438+
434439
/// Coerce the given tuple to another tuple type.
435440
///
436441
/// \param expr The expression we're converting.
@@ -5535,16 +5540,19 @@ namespace {
55355540

55365541
// FIXME: Expansion should be lazy.
55375542
// i.e. 'ExpandMacroExpansionExprRequest' should be sinked into
5538-
// 'getRewritten()', and performed on-demand.
5543+
// 'getRewritten()', and performed on-demand. Unfortunately that requires
5544+
// auditing every ASTWalker's `getMacroWalkingBehavior` since
5545+
// `MacroWalking::Expansion` does not actually kick expansion.
55395546
if (!cs.Options.contains(ConstraintSystemFlags::DisableMacroExpansions) &&
55405547
// Do not expand macros inside macro arguments. For example for
55415548
// '#stringify(#assert(foo))' when typechecking `#assert(foo)`,
55425549
// we don't want to expand it.
55435550
llvm::none_of(llvm::ArrayRef(ExprStack).drop_back(1),
55445551
[](Expr *E) { return isa<MacroExpansionExpr>(E); })) {
5545-
(void)evaluateOrDefault(cs.getASTContext().evaluator,
5546-
ExpandMacroExpansionExprRequest{E},
5547-
std::nullopt);
5552+
// We need to delay the expansion until we're done applying the solution
5553+
// since running MiscDiagnostics on the expansion may walk up and query
5554+
// the type of a parent closure, e.g `diagnoseImplicitSelfUseInClosure`.
5555+
addMacroToExpand(E);
55485556
}
55495557

55505558
cs.cacheExprTypes(E);
@@ -5615,6 +5623,14 @@ namespace {
56155623
// Type-check any local decls encountered.
56165624
for (auto *D : LocalDeclsToTypeCheck)
56175625
TypeChecker::typeCheckDecl(D);
5626+
5627+
// Expand any macros encountered.
5628+
// FIXME: Expansion should be lazy.
5629+
auto &eval = cs.getASTContext().evaluator;
5630+
for (auto *E : MacrosToExpand) {
5631+
(void)evaluateOrDefault(eval, ExpandMacroExpansionExprRequest{E},
5632+
std::nullopt);
5633+
}
56185634
}
56195635

56205636
/// Diagnose an optional injection that is probably not what the

test/Macros/macro_misc_diags.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,28 @@ _ = #trailingClosure {
9898
// CHECK-DIAG: Client.swift:[[@LINE-1]]:27: warning: trailing closure in this context is confusable with the body of the statement; pass as a parenthesized argument to silence this warning
9999
// CHECK-DIAG: @__swiftmacro_6Client0017Clientswift_yEEFcfMX[[@LINE-4]]{{.*}}trailingClosurefMf_.swift:2:27: warning: trailing closure in this context is confusable with the body of the statement
100100
}
101+
102+
// rdar://138997009 - Make sure we don't crash in MiscDiagnostics' implicit
103+
// self diagnosis.
104+
struct rdar138997009 {
105+
func foo() {}
106+
func bar() {
107+
_ = {
108+
_ = #trailingClosure {
109+
foo()
110+
}
111+
}
112+
}
113+
}
114+
115+
class rdar138997009_Class {
116+
func foo() {}
117+
func bar() {
118+
_ = {
119+
_ = #trailingClosure {
120+
foo()
121+
// CHECK-DIAG: @__swiftmacro_6Client0017Clientswift_yEEFcfMX[[@LINE-3]]{{.*}}trailingClosurefMf_.swift:2:9: error: call to method 'foo' in closure requires explicit use of 'self' to make capture semantics explicit
122+
}
123+
}
124+
}
125+
}

0 commit comments

Comments
 (0)