Skip to content

Commit 90e42bb

Browse files
committed
[Effects handling] Eliminate Context::getHandled().
We don't want to expose the notion of "handles everything", because that's a honeypot for messing up 'async' checking when making a context change for error-handling, and vice versa. Instead, provide an API to produce a derived context where all errors are handled, and use it for (e.g.) try/try!/try? and exhaustive do-catches.
1 parent ea8217a commit 90e42bb

File tree

1 file changed

+26
-11
lines changed

1 file changed

+26
-11
lines changed

lib/Sema/TypeCheckEffects.cpp

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -857,6 +857,10 @@ class Context {
857857
Kind TheKind;
858858
Optional<AnyFunctionRef> Function;
859859
bool HandlesErrors = false;
860+
861+
/// Whether error-handling queries should ignore the function context, e.g.,
862+
/// for autoclosure and rethrows checks.
863+
bool ErrorHandlingIgnoresFunction = false;
860864
bool IsNonExhaustiveCatch = false;
861865
bool DiagnoseErrorOnTry = false;
862866
InterpolatedStringLiteralExpr *InterpolatedString = nullptr;
@@ -876,6 +880,9 @@ class Context {
876880
if (!HandlesErrors)
877881
return false;
878882

883+
if (ErrorHandlingIgnoresFunction)
884+
return false;
885+
879886
if (!Function)
880887
return false;
881888

@@ -891,17 +898,16 @@ class Context {
891898
if (!Function)
892899
return false;
893900

901+
if (ErrorHandlingIgnoresFunction)
902+
return false;
903+
894904
auto closure = Function->getAbstractClosureExpr();
895905
if (!closure)
896906
return false;
897907

898908
return isa<AutoClosureExpr>(closure);
899909
}
900910

901-
static Context getHandled() {
902-
return Context(/*handlesErrors=*/true, None);
903-
}
904-
905911
static Context forTopLevelCode(TopLevelCodeDecl *D) {
906912
// Top-level code implicitly handles errors and 'async' calls.
907913
return Context(/*handlesErrors=*/true, None);
@@ -976,6 +982,15 @@ class Context {
976982
return copy;
977983
}
978984

985+
/// Form a subcontext that handles all errors, e.g., for the body of a
986+
/// do-catch with exhaustive catch clauses.
987+
Context withHandlesErrors() const {
988+
Context copy = *this;
989+
copy.HandlesErrors = true;
990+
copy.ErrorHandlingIgnoresFunction = true;
991+
return copy;
992+
}
993+
979994
Kind getKind() const { return TheKind; }
980995

981996
bool handlesNothing() const {
@@ -1416,8 +1431,8 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
14161431
}
14171432

14181433
ThrowingKind checkExhaustiveDoBody(DoCatchStmt *S) {
1419-
// This is a handled context.
1420-
ContextScope scope(*this, Context::getHandled());
1434+
// This is a context where errors are handled.
1435+
ContextScope scope(*this, CurContext.withHandlesErrors());
14211436
assert(!Flags.has(ContextFlags::IsInTry) && "do/catch within try?");
14221437
scope.resetCoverageForDoCatch();
14231438

@@ -1474,9 +1489,9 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
14741489
if (doThrowingKind != ThrowingKind::Throws &&
14751490
CurContext.isRethrows()) {
14761491
// If this catch clause is reachable at all, it's because a function
1477-
// parameter throws. So let's temporarily set our context to Handled so
1478-
// the catch body is allowed to throw.
1479-
CurContext = Context::getHandled();
1492+
// parameter throws. So let's temporarily state that the body is allowed
1493+
// to throw.
1494+
CurContext = CurContext.withHandlesErrors();
14801495
}
14811496

14821497
// The catch body just happens in the enclosing context.
@@ -1661,7 +1676,7 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
16611676

16621677
ShouldRecurse_t checkForceTry(ForceTryExpr *E) {
16631678
// Walk the operand. 'try!' handles errors.
1664-
ContextScope scope(*this, Context::getHandled());
1679+
ContextScope scope(*this, CurContext.withHandlesErrors());
16651680
scope.enterTry();
16661681

16671682
E->getSubExpr()->walk(*this);
@@ -1675,7 +1690,7 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
16751690

16761691
ShouldRecurse_t checkOptionalTry(OptionalTryExpr *E) {
16771692
// Walk the operand. 'try?' handles errors.
1678-
ContextScope scope(*this, Context::getHandled());
1693+
ContextScope scope(*this, CurContext.withHandlesErrors());
16791694
scope.enterTry();
16801695

16811696
E->getSubExpr()->walk(*this);

0 commit comments

Comments
 (0)