@@ -334,9 +334,10 @@ void swift::diagnoseConstantArgumentRequirement(
334
334
const Expr *expr, const DeclContext *declContext) {
335
335
class ConstantReqCallWalker : public ASTWalker {
336
336
DeclContext *DC;
337
+ bool insideClosure;
337
338
338
339
public:
339
- ConstantReqCallWalker (DeclContext *DC) : DC(DC) {}
340
+ ConstantReqCallWalker (DeclContext *DC) : DC(DC), insideClosure( false ) {}
340
341
341
342
// Descend until we find a call expressions. Note that the input expression
342
343
// could be an assign expression or another expression that contains the
@@ -347,10 +348,15 @@ void swift::diagnoseConstantArgumentRequirement(
347
348
if (auto *closureExpr = dyn_cast<ClosureExpr>(expr)) {
348
349
return walkToClosureExprPre (closureExpr);
349
350
}
351
+
350
352
// Interpolated expressions' bodies will be type checked
351
353
// separately so exit early to avoid duplicate diagnostics.
354
+ // The caveat is that they won't be checked inside closure
355
+ // bodies because we manually check all closures to avoid
356
+ // duplicate diagnostics. Therefore we must still descend into
357
+ // interpolated expressions if we are inside of a closure.
352
358
if (!expr || isa<ErrorExpr>(expr) || !expr->getType () ||
353
- isa<InterpolatedStringLiteralExpr>(expr))
359
+ ( isa<InterpolatedStringLiteralExpr>(expr) && !insideClosure ))
354
360
return {false , expr};
355
361
if (auto *callExpr = dyn_cast<CallExpr>(expr)) {
356
362
diagnoseConstantArgumentRequirementOfCall (callExpr, DC->getASTContext ());
@@ -359,33 +365,30 @@ void swift::diagnoseConstantArgumentRequirement(
359
365
}
360
366
361
367
std::pair<bool , Expr *> walkToClosureExprPre (ClosureExpr *closure) {
362
- auto &ctx = DC->getASTContext ();
363
-
364
- if (closure->hasSingleExpressionBody () ||
365
- ctx.TypeCheckerOpts .EnableMultiStatementClosureInference ) {
366
- // Closure bodies are not visited directly by the ASTVisitor,
367
- // so we must descend into the body manuall and set the
368
- // DeclContext to that of the closure.
369
- DC = closure;
370
- return {true , closure};
371
- }
372
- return {false , closure};
368
+ DC = closure;
369
+ insideClosure = true ;
370
+ return {true , closure};
373
371
}
374
372
375
373
Expr *walkToExprPost (Expr *expr) override {
376
374
if (auto *closureExpr = dyn_cast<ClosureExpr>(expr)) {
377
375
// Reset the DeclContext to the outer scope if we descended
378
- // into a closure expr.
376
+ // into a closure expr and check whether or not we are still
377
+ // within a closure context.
379
378
DC = closureExpr->getParent ();
379
+ insideClosure = isa<ClosureExpr>(DC);
380
380
}
381
381
return expr;
382
382
}
383
-
384
- std::pair<bool , Stmt *> walkToStmtPre (Stmt *stmt) override {
385
- return {true , stmt};
386
- }
387
383
};
388
384
385
+ // We manually check closure bodies from their outer contexts,
386
+ // so bail early if we are being called directly on expressions
387
+ // inside of a closure body.
388
+ if (isa<ClosureExpr>(declContext)) {
389
+ return ;
390
+ }
391
+
389
392
ConstantReqCallWalker walker (const_cast <DeclContext *>(declContext));
390
393
const_cast <Expr *>(expr)->walk (walker);
391
394
}
0 commit comments