|
24 | 24 | #include "swift/AST/NameLookupRequests.h"
|
25 | 25 | #include "swift/AST/Pattern.h"
|
26 | 26 | #include "swift/AST/SourceFile.h"
|
| 27 | +#include "swift/AST/TypeCheckRequests.h" |
27 | 28 | #include "swift/Basic/Defer.h"
|
28 | 29 | #include "swift/Basic/SourceManager.h"
|
29 | 30 | #include "swift/Basic/Statistic.h"
|
@@ -4617,6 +4618,65 @@ static void diagnoseComparisonWithNaN(const Expr *E, const DeclContext *DC) {
|
4617 | 4618 | const_cast<Expr *>(E)->walk(Walker);
|
4618 | 4619 | }
|
4619 | 4620 |
|
| 4621 | +namespace { |
| 4622 | + |
| 4623 | +class CompletionHandlerUsageChecker final : public ASTWalker { |
| 4624 | + ASTContext &ctx; |
| 4625 | + |
| 4626 | +public: |
| 4627 | + CompletionHandlerUsageChecker(ASTContext &ctx) : ctx(ctx) {} |
| 4628 | + |
| 4629 | + bool walkToDeclPre(Decl *D) override { return !isa<PatternBindingDecl>(D); } |
| 4630 | + |
| 4631 | + std::pair<bool, Expr *> walkToExprPre(Expr *expr) override { |
| 4632 | + if (ClosureExpr *closure = dyn_cast<ClosureExpr>(expr)) |
| 4633 | + return {closure->isBodyAsync(), closure}; |
| 4634 | + |
| 4635 | + if (ApplyExpr *call = dyn_cast<ApplyExpr>(expr)) { |
| 4636 | + if (DeclRefExpr *fnDeclExpr = dyn_cast<DeclRefExpr>(call->getFn())) { |
| 4637 | + ValueDecl *fnDecl = fnDeclExpr->getDecl(); |
| 4638 | + CompletionHandlerAsyncAttr *asyncAltAttr = |
| 4639 | + fnDecl->getAttrs().getAttribute<CompletionHandlerAsyncAttr>(); |
| 4640 | + if (asyncAltAttr) { |
| 4641 | + // Ensure that the attribute typechecks, |
| 4642 | + // this also resolves the async function decl. |
| 4643 | + if (!evaluateOrDefault( |
| 4644 | + ctx.evaluator, |
| 4645 | + TypeCheckCompletionHandlerAsyncAttrRequest{ |
| 4646 | + cast<AbstractFunctionDecl>(fnDecl), asyncAltAttr}, |
| 4647 | + false)) { |
| 4648 | + return {false, call}; |
| 4649 | + } |
| 4650 | + ctx.Diags.diagnose(call->getLoc(), diag::warn_use_async_alternative); |
| 4651 | + ctx.Diags.diagnose(asyncAltAttr->AsyncFunctionDecl->getLoc(), |
| 4652 | + diag::decl_declared_here, |
| 4653 | + asyncAltAttr->AsyncFunctionDecl->getName()); |
| 4654 | + } |
| 4655 | + } |
| 4656 | + } |
| 4657 | + return {true, expr}; |
| 4658 | + } |
| 4659 | +}; |
| 4660 | + |
| 4661 | +} // namespace |
| 4662 | + |
| 4663 | +void swift::checkFunctionAsyncUsage(AbstractFunctionDecl *decl) { |
| 4664 | + if (!decl->isAsyncContext()) |
| 4665 | + return; |
| 4666 | + CompletionHandlerUsageChecker checker(decl->getASTContext()); |
| 4667 | + BraceStmt *body = decl->getBody(); |
| 4668 | + if (body) |
| 4669 | + body->walk(checker); |
| 4670 | +} |
| 4671 | + |
| 4672 | +void swift::checkPatternBindingDeclAsyncUsage(PatternBindingDecl *decl) { |
| 4673 | + CompletionHandlerUsageChecker checker(decl->getASTContext()); |
| 4674 | + for (Expr *init : decl->initializers()) { |
| 4675 | + if (auto closure = dyn_cast_or_null<ClosureExpr>(init)) |
| 4676 | + closure->walk(checker); |
| 4677 | + } |
| 4678 | +} |
| 4679 | + |
4620 | 4680 | //===----------------------------------------------------------------------===//
|
4621 | 4681 | // High-level entry points.
|
4622 | 4682 | //===----------------------------------------------------------------------===//
|
|
0 commit comments