Skip to content

Commit 4bbfba7

Browse files
committed
[Typed throws] Rethrows functions always throw any Error
Rethrows functions only throw when their closure arguments throw. However, they are free to translate the errors thrown from the closure arguments in any way they want, and are therefore untyped. Ensure that calls to `rethrows` functions are always treated as throwing `any Error` if their closure arguments throw anything.
1 parent 8ca5483 commit 4bbfba7

File tree

2 files changed

+28
-3
lines changed

2 files changed

+28
-3
lines changed

lib/Sema/TypeCheckEffects.cpp

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,17 @@ class Classification {
718718
return result;
719719
}
720720

721+
/// Return a classification that promotes a typed throws effect to an
722+
/// untyped throws effect.
723+
Classification promoteToUntypedThrows() const {
724+
if (!hasThrows())
725+
return *this;
726+
727+
Classification result(*this);
728+
result.ThrownError = ThrownError->getASTContext().getErrorExistentialType();
729+
return result;
730+
}
731+
721732
/// Return a classification that only retains the parts of this
722733
/// classification for the requested effect kind.
723734
Classification onlyEffect(EffectKind kind) const {
@@ -1109,9 +1120,15 @@ class ApplyClassifier {
11091120
}
11101121

11111122
for (unsigned i = 0, e = params.size(); i < e; ++i) {
1112-
result.merge(classifyArgument(args->getExpr(i),
1113-
params[i].getParameterType(),
1114-
kind));
1123+
auto argClassification = classifyArgument(
1124+
args->getExpr(i), params[i].getParameterType(), kind);
1125+
1126+
// Rethrows is untyped, so
1127+
if (kind == EffectKind::Throws) {
1128+
argClassification = argClassification.promoteToUntypedThrows();
1129+
}
1130+
1131+
result.merge(argClassification);
11151132
}
11161133

11171134
return;

test/decl/func/typed_throws.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,3 +146,11 @@ extension Either: Error where First: Error, Second: Error { }
146146
func f<E1, E2>(_ error: Either<E1, E2>) throws(Either<E1, E2>) {
147147
throw error
148148
}
149+
150+
// Ensure that calls to 'rethrows' functions are always treated as throwing `any
151+
// Error`.
152+
func rethrowingFunc(body: () throws -> Void) rethrows { }
153+
154+
func typedCallsRethrowingFunc<E>(body: () throws(E) -> Void) throws(E) {
155+
try rethrowingFunc(body: body) // expected-error{{thrown expression type 'any Error' cannot be converted to error type 'E'}}
156+
}

0 commit comments

Comments
 (0)