Skip to content

Commit 11e7a69

Browse files
committed
Erase existential thrown error types
When performing a throwing operation on an opened existential, the thrown error type could be dependent on the opened existential type, e.g., if the thrown error type is an associated type of one of the corresponding protocols. In such cases, type-erase the thrown error type at the point where it is thrown so that the opened archetype cannot "escape" the enclosing opened-existential operation via throwing. There is an alternative approach we could take that has `OpenExistentialExpr` handle the type erasure of the thrown error type. This would make `OpenExistentialExpr` a catch node, which would type-erase and then rethrow. This is arguably better, because it could mean fewer places where we do the type erasure and is more in line with the design of opened archetypes. However, it would also be much more invasive, and we should be able to do this later. Fixes rdar://124273722.
1 parent 0b0959a commit 11e7a69

File tree

2 files changed

+37
-1
lines changed

2 files changed

+37
-1
lines changed

lib/Sema/TypeCheckEffects.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -800,6 +800,24 @@ static bool isRethrowingDueToAsyncSequence(DeclContext *rethrowsDC) {
800800
return true;
801801
}
802802

803+
/// Type-erase the opened archetypes in the given type, if there is one.
804+
static Type typeEraseOpenedArchetypes(Type type) {
805+
if (!type || !type->hasOpenedExistential())
806+
return type;
807+
808+
const OpenedArchetypeType *root = nullptr;
809+
type.visit([&](Type type) {
810+
if (auto opened = dyn_cast<OpenedArchetypeType>(type.getPointer())) {
811+
root = opened->getRoot();
812+
}
813+
});
814+
815+
if (!root)
816+
return type;
817+
818+
return constraints::typeEraseOpenedArchetypesWithRoot(type, root);
819+
}
820+
803821
/// A type expressing the result of classifying whether a call or function
804822
/// throws or is async.
805823
class Classification {
@@ -928,7 +946,7 @@ class Classification {
928946

929947
result.ThrowKind = conditionalKind;
930948
result.ThrowReason = reason;
931-
result.ThrownError = thrownError;
949+
result.ThrownError = typeEraseOpenedArchetypes(thrownError);
932950
return result;
933951
}
934952

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: %target-swift-frontend -disable-availability-checking %s -emit-sil -o /dev/null -verify
2+
3+
// RUN: %target-swift-frontend -disable-availability-checking %s -dump-ast 2>&1 | %FileCheck %s
4+
5+
// REQUIRES: concurrency
6+
7+
extension Error {
8+
func printMe() { }
9+
}
10+
11+
func test(seq: any AsyncSequence) async {
12+
// CHECK: "error" interface type="any Error"
13+
do {
14+
for try await _ in seq { }
15+
} catch {
16+
error.printMe()
17+
}
18+
}

0 commit comments

Comments
 (0)