Skip to content

Commit 524887b

Browse files
committed
[Effects handling] Eliminate Context::Kind::RethrowingFunction.
We can determine whether we have a rethrowing function based on the function declaration itself.
1 parent f40de80 commit 524887b

File tree

1 file changed

+36
-31
lines changed

1 file changed

+36
-31
lines changed

lib/Sema/TypeCheckEffects.cpp

Lines changed: 36 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -826,9 +826,6 @@ class Context {
826826
/// A non-throwing function.
827827
NonThrowingFunction,
828828

829-
/// A rethrowing function.
830-
RethrowingFunction,
831-
832829
/// A default argument expression.
833830
DefaultArgument,
834831

@@ -864,12 +861,27 @@ class Context {
864861
Optional<AnyFunctionRef> Function;
865862
bool IsNonExhaustiveCatch = false;
866863
bool DiagnoseErrorOnTry = false;
867-
DeclContext *RethrowsDC = nullptr;
868864
InterpolatedStringLiteralExpr *InterpolatedString = nullptr;
869865

870866
explicit Context(Kind kind, Optional<AnyFunctionRef> function = None)
871867
: TheKind(kind), Function(function) {}
872868

869+
public:
870+
/// Whether this is a function that rethrows.
871+
bool isRethrows() const {
872+
if (getKind() != Kind::Handled)
873+
return false;
874+
875+
if (!Function)
876+
return false;
877+
878+
auto fn = Function->getAbstractFunctionDecl();
879+
if (!fn)
880+
return false;
881+
882+
return fn->getAttrs().hasAttribute<RethrowsAttr>();
883+
}
884+
873885
/// Whether this is an autoclosure.
874886
bool isAutoClosure() const {
875887
if (!Function)
@@ -882,7 +894,6 @@ class Context {
882894
return isa<AutoClosureExpr>(closure);
883895
}
884896

885-
public:
886897
static Context getHandled() {
887898
return Context(Kind::Handled);
888899
}
@@ -893,12 +904,6 @@ class Context {
893904
}
894905

895906
static Context forFunction(AbstractFunctionDecl *D) {
896-
if (D->getAttrs().hasAttribute<RethrowsAttr>()) {
897-
Context result(Kind::RethrowingFunction, AnyFunctionRef(D));
898-
result.RethrowsDC = D;
899-
return result;
900-
}
901-
902907
// HACK: If the decl is the synthesized getter for a 'lazy' property, then
903908
// treat the context as a property initializer in order to produce a better
904909
// diagnostic; the only code we should be diagnosing on is within the
@@ -972,8 +977,7 @@ class Context {
972977
Kind getKind() const { return TheKind; }
973978

974979
bool handlesNothing() const {
975-
return getKind() != Kind::Handled &&
976-
getKind() != Kind::RethrowingFunction;
980+
return getKind() != Kind::Handled;
977981
}
978982
bool handles(ThrowingKind errorKind) const {
979983
switch (errorKind) {
@@ -982,17 +986,23 @@ class Context {
982986

983987
// A call that's rethrowing-only can be handled by 'rethrows'.
984988
case ThrowingKind::RethrowingOnly:
985-
return !handlesNothing();
989+
return getKind() == Kind::Handled;
986990

987991
// An operation that always throws can only be handled by an
988992
// all-handling context.
989993
case ThrowingKind::Throws:
990-
return getKind() == Kind::Handled;
994+
return getKind() == Kind::Handled && !isRethrows();
991995
}
992996
llvm_unreachable("bad error kind");
993997
}
994998

995-
DeclContext *getRethrowsDC() const { return RethrowsDC; }
999+
DeclContext *getRethrowsDC() const {
1000+
if (!isRethrows())
1001+
return nullptr;
1002+
1003+
return Function->getAbstractFunctionDecl();
1004+
}
1005+
9961006
InterpolatedStringLiteralExpr * getInterpolatedString() const {
9971007
return InterpolatedString;
9981008
}
@@ -1098,8 +1108,7 @@ class Context {
10981108
// Allow the diagnostic to fire on the 'try' if we don't have
10991109
// anything else to say.
11001110
if (isTryCovered && !reason.isRethrowsCall() &&
1101-
getKind() == Kind::NonThrowingFunction &&
1102-
!isAutoClosure()) {
1111+
!isRethrows() && !isAutoClosure()) {
11031112
DiagnoseErrorOnTry = true;
11041113
return;
11051114
}
@@ -1117,18 +1126,15 @@ class Context {
11171126
const PotentialThrowReason &reason) {
11181127
switch (getKind()) {
11191128
case Kind::Handled:
1120-
llvm_unreachable("throw site is handled!");
1121-
1122-
// TODO: Doug suggested that we could generate one error per
1123-
// non-throwing function with throw sites within it, possibly with
1124-
// notes for the throw sites.
1129+
if (isRethrows()) {
1130+
diagnoseThrowInLegalContext(Diags, E, isTryCovered, reason,
1131+
diag::throw_in_rethrows_function,
1132+
diag::throwing_call_in_rethrows_function,
1133+
diag::tryless_throwing_call_in_rethrows_function);
1134+
return;
1135+
}
11251136

1126-
case Kind::RethrowingFunction:
1127-
diagnoseThrowInLegalContext(Diags, E, isTryCovered, reason,
1128-
diag::throw_in_rethrows_function,
1129-
diag::throwing_call_in_rethrows_function,
1130-
diag::tryless_throwing_call_in_rethrows_function);
1131-
return;
1137+
llvm_unreachable("throw site is handled!");
11321138

11331139
case Kind::NonThrowingFunction:
11341140
if (IsNonExhaustiveCatch) {
@@ -1186,7 +1192,6 @@ class Context {
11861192
void diagnoseUnhandledTry(DiagnosticEngine &Diags, TryExpr *E) {
11871193
switch (getKind()) {
11881194
case Kind::Handled:
1189-
case Kind::RethrowingFunction:
11901195
llvm_unreachable("try is handled!");
11911196

11921197
case Kind::NonThrowingFunction:
@@ -1471,7 +1476,7 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
14711476

14721477
auto savedContext = CurContext;
14731478
if (doThrowingKind != ThrowingKind::Throws &&
1474-
CurContext.getKind() == Context::Kind::RethrowingFunction) {
1479+
CurContext.isRethrows()) {
14751480
// If this catch clause is reachable at all, it's because a function
14761481
// parameter throws. So let's temporarily set our context to Handled so
14771482
// the catch body is allowed to throw.

0 commit comments

Comments
 (0)