@@ -219,6 +219,8 @@ class EffectsHandlingWalker : public ASTWalker {
219219 recurse = asImpl ().checkOptionalTry (optionalTryExpr);
220220 } else if (auto apply = dyn_cast<ApplyExpr>(E)) {
221221 recurse = asImpl ().checkApply (apply);
222+ } else if (auto declRef = dyn_cast<DeclRefExpr>(E)) {
223+ recurse = asImpl ().checkDeclRef (declRef);
222224 } else if (auto interpolated = dyn_cast<InterpolatedStringLiteralExpr>(E)) {
223225 recurse = asImpl ().checkInterpolatedStringLiteral (interpolated);
224226 }
@@ -656,6 +658,9 @@ class ApplyClassifier {
656658 Result = std::max (Result, classification.getResult ());
657659 return ShouldRecurse;
658660 }
661+ ShouldRecurse_t checkDeclRef (DeclRefExpr *E) {
662+ return ShouldNotRecurse;
663+ }
659664 ShouldRecurse_t checkThrow (ThrowStmt *E) {
660665 Result = ThrowingKind::Throws;
661666 return ShouldRecurse;
@@ -1271,6 +1276,18 @@ class Context {
12711276 SourceRange highlight;
12721277
12731278 // Generate more specific messages in some cases.
1279+
1280+ // Reference to an 'async let' missing an 'await'.
1281+ if (auto declRef = dyn_cast_or_null<DeclRefExpr>(node.dyn_cast <Expr *>())) {
1282+ if (auto var = dyn_cast<VarDecl>(declRef->getDecl ())) {
1283+ if (var->isAsyncLet ()) {
1284+ ctx.Diags .diagnose (
1285+ declRef->getLoc (), diag::async_let_without_await, var->getName ());
1286+ return ;
1287+ }
1288+ }
1289+ }
1290+
12741291 if (auto apply = dyn_cast_or_null<ApplyExpr>(node.dyn_cast <Expr*>()))
12751292 highlight = apply->getSourceRange ();
12761293
@@ -1293,6 +1310,17 @@ class Context {
12931310 static_cast <unsigned >(getKind ()));
12941311 return ;
12951312 }
1313+
1314+ if (auto declRef = dyn_cast<DeclRefExpr>(e)) {
1315+ if (auto var = dyn_cast<VarDecl>(declRef->getDecl ())) {
1316+ if (var->isAsyncLet ()) {
1317+ Diags.diagnose (
1318+ e->getLoc (), diag::async_let_in_illegal_context,
1319+ var->getName (), static_cast <unsigned >(getKind ()));
1320+ return ;
1321+ }
1322+ }
1323+ }
12961324 }
12971325
12981326 Diags.diagnose (node.getStartLoc (), diag::await_in_illegal_context,
@@ -1312,11 +1340,17 @@ class Context {
13121340
13131341 void diagnoseUnhandledAsyncSite (DiagnosticEngine &Diags, ASTNode node) {
13141342 switch (getKind ()) {
1315- case Kind::PotentiallyHandled:
1343+ case Kind::PotentiallyHandled: {
1344+ unsigned kind = 0 ;
1345+ if (node.isExpr (ExprKind::Await))
1346+ kind = 1 ;
1347+ else if (node.isExpr (ExprKind::DeclRef))
1348+ kind = 2 ;
13161349 Diags.diagnose (node.getStartLoc (), diag::async_in_nonasync_function,
1317- node. isExpr (ExprKind::Await) , isAutoClosure ());
1350+ kind , isAutoClosure ());
13181351 maybeAddAsyncNote (Diags);
13191352 return ;
1353+ }
13201354
13211355 case Kind::EnumElementInitializer:
13221356 case Kind::GlobalVarInitializer:
@@ -1694,6 +1728,21 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
16941728 return !type || type->hasError () ? ShouldNotRecurse : ShouldRecurse;
16951729 }
16961730
1731+ ShouldRecurse_t checkDeclRef (DeclRefExpr *E) {
1732+ if (auto decl = E->getDecl ()) {
1733+ if (auto var = dyn_cast<VarDecl>(decl)) {
1734+ // "Async let" declarations are treated as an asynchronous call
1735+ // (to the underlying task's "get").
1736+ if (var->isAsyncLet ()) {
1737+ checkThrowAsyncSite (
1738+ E, /* requiresTry=*/ false , Classification::forAsync ());
1739+ }
1740+ }
1741+ }
1742+
1743+ return ShouldNotRecurse;
1744+ }
1745+
16971746 ShouldRecurse_t
16981747 checkInterpolatedStringLiteral (InterpolatedStringLiteralExpr *E) {
16991748 ContextScope scope (*this , CurContext.withInterpolatedString (E));
0 commit comments