Skip to content

Commit 512f7b7

Browse files
committed
[TypeCheckEffects] Do not diagnose missing try/await in async let
initializers that involve `if` or `switch` expressions. (cherry picked from commit 2468bb0)
1 parent 194c13c commit 512f7b7

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
@@ -2051,6 +2051,9 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
20512051

20522052
/// Do we have any 'await's in this context?
20532053
HasAnyAwait = 0x80,
2054+
2055+
/// Are we in an 'async let' initializer context?
2056+
InAsyncLet = 0x100,
20542057
};
20552058
private:
20562059
unsigned Bits;
@@ -2196,8 +2199,7 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
21962199
}
21972200

21982201
void enterAsyncLet() {
2199-
Self.Flags.set(ContextFlags::IsTryCovered);
2200-
Self.Flags.set(ContextFlags::IsAsyncCovered);
2202+
Self.Flags.set(ContextFlags::InAsyncLet);
22012203
}
22022204

22032205
void refineLocalContext(Context newContext) {
@@ -2236,6 +2238,11 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
22362238
// 'async'.
22372239
}
22382240

2241+
void setCoverageForSingleValueStmtExpr() {
2242+
resetCoverage();
2243+
Self.Flags.mergeFrom(ContextFlags::InAsyncLet, OldFlags);
2244+
}
2245+
22392246
void preserveCoverageFromSingleValueStmtExpr() {
22402247
// We need to preserve whether we saw any throwing sites, to avoid warning
22412248
// on 'do { let x = if .random() { try ... } else { ... } } catch { ... }'
@@ -2393,7 +2400,7 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
23932400
// For an if/switch expression, we reset coverage such that a 'try'/'await'
23942401
// does not cover the branches.
23952402
ContextScope scope(*this, /*newContext*/ llvm::None);
2396-
scope.resetCoverage();
2403+
scope.setCoverageForSingleValueStmtExpr();
23972404
SVE->getStmt()->walk(*this);
23982405
scope.preserveCoverageFromSingleValueStmtExpr();
23992406
return ShouldNotRecurse;
@@ -2734,7 +2741,8 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
27342741
classification.getAsyncReason());
27352742
}
27362743
// Diagnose async calls that are outside of an await context.
2737-
else if (!Flags.has(ContextFlags::IsAsyncCovered)) {
2744+
else if (!(Flags.has(ContextFlags::IsAsyncCovered) ||
2745+
Flags.has(ContextFlags::InAsyncLet))) {
27382746
Expr *expr = E.dyn_cast<Expr*>();
27392747
Expr *anchor = walkToAnchor(expr, parentMap,
27402748
CurContext.isWithinInterpolatedString());
@@ -2770,7 +2778,8 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
27702778
break;
27712779

27722780
bool isTryCovered =
2773-
(!requiresTry || Flags.has(ContextFlags::IsTryCovered));
2781+
(!requiresTry || Flags.has(ContextFlags::IsTryCovered) ||
2782+
Flags.has(ContextFlags::InAsyncLet));
27742783
if (!CurContext.handlesThrows(throwsKind)) {
27752784
CurContext.diagnoseUnhandledThrowSite(Ctx.Diags, E, isTryCovered,
27762785
classification.getThrowReason());

test/expr/unary/if_expr.swift

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

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

0 commit comments

Comments
 (0)