Skip to content

Commit 134f4e5

Browse files
committed
[Diagnostics] Fix a crash when using withoutActuallyEscaping incorrectly
Teach `eraseOpenedExistentials` how to handle `OpaqueValueExpr` associated with `MakeTemporarilyEscapableExpr`. Resolves: rdar://problem/35773761
1 parent 6b899b6 commit 134f4e5

File tree

2 files changed

+19
-5
lines changed

2 files changed

+19
-5
lines changed

lib/Sema/CSDiag.cpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2111,13 +2111,17 @@ static void eraseOpenedExistentials(Expr *&expr, ConstraintSystem &CS) {
21112111
// Walk the base expression to ensure we erase any existentials within
21122112
// it.
21132113
base = base->walk(*this);
2114-
2115-
bool inserted = OpenExistentials.insert({archetypeVal, base}).second;
2116-
assert(inserted && "OpaqueValue appears multiple times?");
2117-
(void)inserted;
2114+
2115+
registerOpaqueValue(archetypeVal, base);
21182116
return { true, OOE->getSubExpr() };
21192117
}
2120-
2118+
2119+
if (auto *MTEE = dyn_cast<MakeTemporarilyEscapableExpr>(expr)) {
2120+
registerOpaqueValue(MTEE->getOpaqueValue(),
2121+
MTEE->getNonescapingClosureValue());
2122+
return {true, MTEE->getSubExpr()};
2123+
}
2124+
21212125
if (auto OVE = dyn_cast<OpaqueValueExpr>(expr)) {
21222126
auto value = OpenExistentials.find(OVE);
21232127
assert(value != OpenExistentials.end() &&
@@ -2166,6 +2170,12 @@ static void eraseOpenedExistentials(Expr *&expr, ConstraintSystem &CS) {
21662170
std::pair<bool, Stmt *> walkToStmtPre(Stmt *S) override {
21672171
return { false, S };
21682172
}
2173+
2174+
void registerOpaqueValue(OpaqueValueExpr *opaque, Expr *base) {
2175+
bool inserted = OpenExistentials.insert({opaque, base}).second;
2176+
assert(inserted && "OpaqueValue appears multiple times?");
2177+
(void)inserted;
2178+
}
21692179
};
21702180

21712181
expr = expr->walk(ExistentialEraser(CS));
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// RUN: %target-typecheck-verify-swift %s
2+
3+
let b: () -> Void = withoutActuallyEscaping({ print("hello crash") }, do: { $0() })
4+
// expected-error@-1 {{cannot convert value of type '()' to specified type '() -> Void'}}

0 commit comments

Comments
 (0)