Skip to content

Commit 2468bb0

Browse files
committed
[TypeCheckEffects] Do not diagnose missing try/await in async let
initializers that involve `if` or `switch` expressions.
1 parent 4c604b4 commit 2468bb0

File tree

2 files changed

+24
-5
lines changed

2 files changed

+24
-5
lines changed

lib/Sema/TypeCheckEffects.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2562,6 +2562,9 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
25622562

25632563
/// Do we have any 'await's in this context?
25642564
HasAnyAwait = 0x80,
2565+
2566+
/// Are we in an 'async let' initializer context?
2567+
InAsyncLet = 0x100,
25652568
};
25662569
private:
25672570
unsigned Bits;
@@ -2707,8 +2710,7 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
27072710
}
27082711

27092712
void enterAsyncLet() {
2710-
Self.Flags.set(ContextFlags::IsTryCovered);
2711-
Self.Flags.set(ContextFlags::IsAsyncCovered);
2713+
Self.Flags.set(ContextFlags::InAsyncLet);
27122714
}
27132715

27142716
void refineLocalContext(Context newContext) {
@@ -2747,6 +2749,11 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
27472749
// 'async'.
27482750
}
27492751

2752+
void setCoverageForSingleValueStmtExpr() {
2753+
resetCoverage();
2754+
Self.Flags.mergeFrom(ContextFlags::InAsyncLet, OldFlags);
2755+
}
2756+
27502757
void preserveCoverageFromSingleValueStmtExpr() {
27512758
// We need to preserve whether we saw any throwing sites, to avoid warning
27522759
// on 'do { let x = if .random() { try ... } else { ... } } catch { ... }'
@@ -2918,7 +2925,7 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
29182925
// For an if/switch expression, we reset coverage such that a 'try'/'await'
29192926
// does not cover the branches.
29202927
ContextScope scope(*this, /*newContext*/ llvm::None);
2921-
scope.resetCoverage();
2928+
scope.setCoverageForSingleValueStmtExpr();
29222929
SVE->getStmt()->walk(*this);
29232930
scope.preserveCoverageFromSingleValueStmtExpr();
29242931
return ShouldNotRecurse;
@@ -3173,7 +3180,8 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
31733180
classification.getAsyncReason());
31743181
}
31753182
// Diagnose async calls that are outside of an await context.
3176-
else if (!Flags.has(ContextFlags::IsAsyncCovered)) {
3183+
else if (!(Flags.has(ContextFlags::IsAsyncCovered) ||
3184+
Flags.has(ContextFlags::InAsyncLet))) {
31773185
Expr *expr = E.dyn_cast<Expr*>();
31783186
Expr *anchor = walkToAnchor(expr, parentMap,
31793187
CurContext.isWithinInterpolatedString());
@@ -3209,7 +3217,8 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
32093217
break;
32103218

32113219
bool isTryCovered =
3212-
(!requiresTry || Flags.has(ContextFlags::IsTryCovered));
3220+
(!requiresTry || Flags.has(ContextFlags::IsTryCovered) ||
3221+
Flags.has(ContextFlags::InAsyncLet));
32133222
if (!CurContext.handlesThrows(throwsKind)) {
32143223
CurContext.diagnoseUnhandledThrowSite(Ctx.Diags, E, isTryCovered,
32153224
classification.getThrowReason());

test/expr/unary/if_expr.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1492,6 +1492,16 @@ func tryAwaitIf15(_ fn: () async throws -> Int) async rethrows -> Int {
14921492
}
14931493
}
14941494

1495+
func asyncLetIf(cond: Bool, _ fn: () async throws -> Int) async throws -> Int {
1496+
async let x = if cond {
1497+
fn()
1498+
} else {
1499+
0
1500+
}
1501+
1502+
return try await x
1503+
}
1504+
14951505
struct AnyEraserP: EraserP {
14961506
init<T: EraserP>(erasing: T) {}
14971507
}

0 commit comments

Comments
 (0)