@@ -269,6 +269,9 @@ class PotentialThrowReason {
269269 // / The function calls an unconditionally throwing function.
270270 CallThrows,
271271
272+ // / The initializer of an 'async let' unconditionally throws.
273+ AsyncLetThrows,
274+
272275 // / The function is 'rethrows', and it was passed an explicit
273276 // / argument that was not rethrowing-only in this context.
274277 CallRethrowsWithExplicitThrowingArgument,
@@ -282,7 +285,8 @@ class PotentialThrowReason {
282285 switch (k) {
283286 case Kind::Throw: return " Throw" ;
284287 case Kind::CallThrows: return " CallThrows" ;
285- case Kind::CallRethrowsWithExplicitThrowingArgument:
288+ case Kind::AsyncLetThrows: return " AsyncLetThrows" ;
289+ case Kind::CallRethrowsWithExplicitThrowingArgument:
286290 return " CallRethrowsWithExplicitThrowingArgument" ;
287291 case Kind::CallRethrowsWithDefaultThrowingArgument:
288292 return " CallRethrowsWithDefaultThrowingArgument" ;
@@ -309,6 +313,9 @@ class PotentialThrowReason {
309313 static PotentialThrowReason forThrow () {
310314 return PotentialThrowReason (Kind::Throw);
311315 }
316+ static PotentialThrowReason forThrowingAsyncLet () {
317+ return PotentialThrowReason (Kind::AsyncLetThrows);
318+ }
312319
313320 Kind getKind () const { return TheKind; }
314321
@@ -1124,6 +1131,7 @@ class Context {
11241131 case PotentialThrowReason::Kind::Throw:
11251132 llvm_unreachable (" should already have been covered" );
11261133 case PotentialThrowReason::Kind::CallThrows:
1134+ case PotentialThrowReason::Kind::AsyncLetThrows:
11271135 // Already fully diagnosed.
11281136 return ;
11291137 case PotentialThrowReason::Kind::CallRethrowsWithExplicitThrowingArgument:
@@ -1141,6 +1149,9 @@ class Context {
11411149 const PotentialThrowReason &reason) {
11421150 auto &Diags = ctx.Diags ;
11431151 auto message = diag::throwing_call_without_try;
1152+ if (reason.getKind () == PotentialThrowReason::Kind::AsyncLetThrows)
1153+ message = diag::throwing_async_let_without_try;
1154+
11441155 auto loc = E.getStartLoc ();
11451156 SourceLoc insertLoc;
11461157 SourceRange highlight;
@@ -1781,10 +1792,25 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
17811792 if (auto decl = E->getDecl ()) {
17821793 if (auto var = dyn_cast<VarDecl>(decl)) {
17831794 // "Async let" declarations are treated as an asynchronous call
1784- // (to the underlying task's "get").
1795+ // (to the underlying task's "get"). If the initializer was throwing,
1796+ // then the access is also treated as throwing.
17851797 if (var->isAsyncLet ()) {
1786- checkThrowAsyncSite (
1787- E, /* requiresTry=*/ false , Classification::forAsync ());
1798+ // If the initializer could throw, we will have a 'try' in the
1799+ // application of its autoclosure.
1800+ bool throws = false ;
1801+ if (auto init = var->getParentInitializer ()) {
1802+ if (auto await = dyn_cast<AwaitExpr>(init))
1803+ init = await->getSubExpr ();
1804+ if (isa<TryExpr>(init))
1805+ throws = true ;
1806+ }
1807+
1808+ auto classification =
1809+ throws ? Classification::forThrow (
1810+ PotentialThrowReason::forThrowingAsyncLet (),
1811+ /* isAsync=*/ true )
1812+ : Classification::forAsync ();
1813+ checkThrowAsyncSite (E, /* requiresTry=*/ throws, classification);
17881814 }
17891815 }
17901816 }
0 commit comments