Skip to content

Commit 5e46ca5

Browse files
committed
Coerce the parameter of the parameter to withoutActuallyEscaping to actually be escaping.
People can call `withoutActuallyEscaping` and give it a `do:` body function that, well, doesn't actually take an escaping closure argument as in: ```swift func foo(_ f: (() -> Void) -> Void, _ b: () -> Void) { return withoutActuallyEscaping(b, do: f) } ``` and this wouldn't really work because the did-it-escape checking relies on having a refcounted object to probe, aside from triggering a bunch of assertion failures in SILGen which assumed the parameter would be escaping. Fixes rdar://104477418.
1 parent d75b65c commit 5e46ca5

File tree

2 files changed

+17
-3
lines changed

2 files changed

+17
-3
lines changed

lib/Sema/CSApply.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7844,18 +7844,27 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType,
78447844
auto *body = args->getExpr(1);
78457845
auto bodyTy = cs.getType(body)->getWithoutSpecifierType();
78467846
auto bodyFnTy = bodyTy->castTo<FunctionType>();
7847-
auto escapableParams = bodyFnTy->getParams();
78487847
auto resultType = bodyFnTy->getResult();
78497848

78507849
// The body is immediately called, so is obviously noescape.
7850+
// Coerce the argument function to be escaping even if it happens to
7851+
// be nonescaping, since we need the dynamic state of the escaping
7852+
// closure to do the dynamic noescape check.
7853+
auto bodyArgFnTy = bodyFnTy->getParams()[0].getPlainType()
7854+
->castTo<FunctionType>();
7855+
7856+
bodyArgFnTy = cast<FunctionType>(
7857+
bodyArgFnTy->withExtInfo(bodyArgFnTy->getExtInfo().withNoEscape(false)));
78517858
bodyFnTy = cast<FunctionType>(
7852-
bodyFnTy->withExtInfo(bodyFnTy->getExtInfo().withNoEscape()));
7859+
FunctionType::get(bodyFnTy->getParams()[0].withType(bodyArgFnTy),
7860+
bodyFnTy->getResult())
7861+
->withExtInfo(bodyFnTy->getExtInfo().withNoEscape()));
78537862
body = coerceToType(body, bodyFnTy, locator);
78547863
assert(body && "can't make nonescaping?!");
78557864

78567865
auto escapable = new (ctx)
78577866
OpaqueValueExpr(apply->getFn()->getSourceRange(), Type());
7858-
cs.setType(escapable, escapableParams[0].getOldType());
7867+
cs.setType(escapable, bodyArgFnTy);
78597868

78607869
auto *argList = ArgumentList::forImplicitUnlabeled(ctx, {escapable});
78617870
auto callSubExpr = CallExpr::createImplicit(ctx, body, argList);
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// RUN: %target-swift-emit-silgen -verify %s
2+
3+
func foo(_ f: (() -> Void) -> Void, _ b: () -> Void) {
4+
return withoutActuallyEscaping(b, do: f)
5+
}

0 commit comments

Comments
 (0)