@@ -334,9 +334,10 @@ void swift::diagnoseConstantArgumentRequirement(
334334 const Expr *expr, const DeclContext *declContext) {
335335 class ConstantReqCallWalker : public ASTWalker {
336336 DeclContext *DC;
337+ bool insideClosure;
337338
338339 public:
339- ConstantReqCallWalker (DeclContext *DC) : DC(DC) {}
340+ ConstantReqCallWalker (DeclContext *DC) : DC(DC), insideClosure( false ) {}
340341
341342 // Descend until we find a call expressions. Note that the input expression
342343 // could be an assign expression or another expression that contains the
@@ -347,10 +348,15 @@ void swift::diagnoseConstantArgumentRequirement(
347348 if (auto *closureExpr = dyn_cast<ClosureExpr>(expr)) {
348349 return walkToClosureExprPre (closureExpr);
349350 }
351+
350352 // Interpolated expressions' bodies will be type checked
351353 // 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.
352358 if (!expr || isa<ErrorExpr>(expr) || !expr->getType () ||
353- isa<InterpolatedStringLiteralExpr>(expr))
359+ ( isa<InterpolatedStringLiteralExpr>(expr) && !insideClosure ))
354360 return {false , expr};
355361 if (auto *callExpr = dyn_cast<CallExpr>(expr)) {
356362 diagnoseConstantArgumentRequirementOfCall (callExpr, DC->getASTContext ());
@@ -359,33 +365,30 @@ void swift::diagnoseConstantArgumentRequirement(
359365 }
360366
361367 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};
373371 }
374372
375373 Expr *walkToExprPost (Expr *expr) override {
376374 if (auto *closureExpr = dyn_cast<ClosureExpr>(expr)) {
377375 // 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.
379378 DC = closureExpr->getParent ();
379+ insideClosure = isa<ClosureExpr>(DC);
380380 }
381381 return expr;
382382 }
383-
384- std::pair<bool , Stmt *> walkToStmtPre (Stmt *stmt) override {
385- return {true , stmt};
386- }
387383 };
388384
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+
389392 ConstantReqCallWalker walker (const_cast <DeclContext *>(declContext));
390393 const_cast <Expr *>(expr)->walk (walker);
391394}
0 commit comments