@@ -269,6 +269,9 @@ class PotentialThrowReason {
269
269
// / The function calls an unconditionally throwing function.
270
270
CallThrows,
271
271
272
+ // / The initializer of an 'async let' unconditionally throws.
273
+ AsyncLetThrows,
274
+
272
275
// / The function is 'rethrows', and it was passed an explicit
273
276
// / argument that was not rethrowing-only in this context.
274
277
CallRethrowsWithExplicitThrowingArgument,
@@ -282,7 +285,8 @@ class PotentialThrowReason {
282
285
switch (k) {
283
286
case Kind::Throw: return " Throw" ;
284
287
case Kind::CallThrows: return " CallThrows" ;
285
- case Kind::CallRethrowsWithExplicitThrowingArgument:
288
+ case Kind::AsyncLetThrows: return " AsyncLetThrows" ;
289
+ case Kind::CallRethrowsWithExplicitThrowingArgument:
286
290
return " CallRethrowsWithExplicitThrowingArgument" ;
287
291
case Kind::CallRethrowsWithDefaultThrowingArgument:
288
292
return " CallRethrowsWithDefaultThrowingArgument" ;
@@ -309,6 +313,9 @@ class PotentialThrowReason {
309
313
static PotentialThrowReason forThrow () {
310
314
return PotentialThrowReason (Kind::Throw);
311
315
}
316
+ static PotentialThrowReason forThrowingAsyncLet () {
317
+ return PotentialThrowReason (Kind::AsyncLetThrows);
318
+ }
312
319
313
320
Kind getKind () const { return TheKind; }
314
321
@@ -1124,6 +1131,7 @@ class Context {
1124
1131
case PotentialThrowReason::Kind::Throw:
1125
1132
llvm_unreachable (" should already have been covered" );
1126
1133
case PotentialThrowReason::Kind::CallThrows:
1134
+ case PotentialThrowReason::Kind::AsyncLetThrows:
1127
1135
// Already fully diagnosed.
1128
1136
return ;
1129
1137
case PotentialThrowReason::Kind::CallRethrowsWithExplicitThrowingArgument:
@@ -1141,6 +1149,9 @@ class Context {
1141
1149
const PotentialThrowReason &reason) {
1142
1150
auto &Diags = ctx.Diags ;
1143
1151
auto message = diag::throwing_call_without_try;
1152
+ if (reason.getKind () == PotentialThrowReason::Kind::AsyncLetThrows)
1153
+ message = diag::throwing_async_let_without_try;
1154
+
1144
1155
auto loc = E.getStartLoc ();
1145
1156
SourceLoc insertLoc;
1146
1157
SourceRange highlight;
@@ -1781,10 +1792,25 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
1781
1792
if (auto decl = E->getDecl ()) {
1782
1793
if (auto var = dyn_cast<VarDecl>(decl)) {
1783
1794
// "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.
1785
1797
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);
1788
1814
}
1789
1815
}
1790
1816
}
0 commit comments