Skip to content

Commit 9939306

Browse files
authored
Merge pull request #9695 from rudkx/fix-rdar32239354
Fix some issues in handling of withoutActuallyEscaping.
2 parents 1a07230 + b8cc015 commit 9939306

File tree

4 files changed

+72
-24
lines changed

4 files changed

+72
-24
lines changed

lib/AST/ASTVerifier.cpp

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1879,35 +1879,51 @@ class Verifier : public ASTWalker {
18791879
Out << "MakeTemporarilyEscapableExpr type does not match subexpression";
18801880
abort();
18811881
}
1882-
1883-
// Closure and opaque value should both be functions, with the closure
1884-
// noescape and the opaque value escapable but otherwise matching.
1885-
auto closureFnTy = E->getNonescapingClosureValue()->getType()
1886-
->getAs<FunctionType>();
1887-
if (!closureFnTy) {
1888-
Out << "MakeTemporarilyEscapableExpr closure type is not a closure";
1882+
1883+
auto call = dyn_cast<CallExpr>(E->getSubExpr());
1884+
if (!call) {
1885+
Out << "MakeTemporarilyEscapableExpr subexpression is not a call\n";
18891886
abort();
18901887
}
1891-
auto opaqueValueFnTy = E->getOpaqueValue()->getType()
1892-
->getAs<FunctionType>();
1893-
if (!opaqueValueFnTy) {
1894-
Out<<"MakeTemporarilyEscapableExpr opaque value type is not a closure";
1888+
1889+
auto callFnTy = call->getFn()->getType()->getAs<FunctionType>();
1890+
if (!callFnTy) {
1891+
Out << "MakeTemporarilyEscapableExpr call does not call function\n";
18951892
abort();
18961893
}
1897-
if (!closureFnTy->isNoEscape()) {
1898-
Out << "MakeTemporarilyEscapableExpr closure type should be noescape";
1894+
if (!callFnTy->getExtInfo().isNoEscape()) {
1895+
Out << "MakeTemporarilyEscapableExpr called function is not noescape\n";
18991896
abort();
19001897
}
1901-
if (opaqueValueFnTy->isNoEscape()) {
1902-
Out << "MakeTemporarilyEscapableExpr opaque value type should be "
1903-
"escaping";
1898+
1899+
auto callArgTy = call->getArg()->getType()->getAs<FunctionType>();
1900+
if (!callArgTy) {
1901+
Out << "MakeTemporarilyEscapableExpr call argument is not a function\n";
1902+
abort();
1903+
}
1904+
1905+
// Closure and opaque value should both be functions, with the closure
1906+
// noescape and the opaque value escapable but otherwise matching.
1907+
auto closureFnTy =
1908+
E->getNonescapingClosureValue()->getType()->getAs<FunctionType>();
1909+
if (!closureFnTy) {
1910+
Out << "MakeTemporarilyEscapableExpr closure type is not a closure\n";
1911+
abort();
1912+
}
1913+
auto opaqueValueFnTy =
1914+
E->getOpaqueValue()->getType()->getAs<FunctionType>();
1915+
if (!opaqueValueFnTy) {
1916+
Out << "MakeTemporarilyEscapableExpr opaque value type is not a "
1917+
"closure\n";
19041918
abort();
19051919
}
1906-
if (!closureFnTy->isEqual(
1907-
opaqueValueFnTy->withExtInfo(opaqueValueFnTy->getExtInfo()
1908-
.withNoEscape()))) {
1920+
auto closureFnNoEscape =
1921+
closureFnTy->withExtInfo(closureFnTy->getExtInfo().withNoEscape());
1922+
auto opaqueValueNoEscape = opaqueValueFnTy->withExtInfo(
1923+
opaqueValueFnTy->getExtInfo().withNoEscape());
1924+
if (!closureFnNoEscape->isEqual(opaqueValueNoEscape)) {
19091925
Out << "MakeTemporarilyEscapableExpr closure and opaque value type "
1910-
"don't match";
1926+
"don't match\n";
19111927
abort();
19121928
}
19131929
}

lib/Sema/CSApply.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6745,7 +6745,8 @@ Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType,
67456745
assert(arg->getNumElements() == 2 && "should have two arguments");
67466746
auto nonescaping = arg->getElements()[0];
67476747
auto body = arg->getElements()[1];
6748-
auto bodyFnTy = cs.getType(body)->castTo<FunctionType>();
6748+
auto bodyTy = cs.getType(body)->getLValueOrInOutObjectType();
6749+
auto bodyFnTy = bodyTy->castTo<FunctionType>();
67496750
auto escapableType = bodyFnTy->getInput();
67506751
auto resultType = bodyFnTy->getResult();
67516752

lib/Sema/CSSimplify.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3682,9 +3682,6 @@ ConstraintSystem::simplifyEscapableFunctionOfConstraint(
36823682

36833683
type2 = getFixedTypeRecursive(type2, flags, /*wantRValue=*/true);
36843684
if (auto fn2 = type2->getAs<FunctionType>()) {
3685-
// We should have the noescape end of the relation.
3686-
if (!fn2->getExtInfo().isNoEscape())
3687-
return SolutionKind::Error;
36883685
// Solve forward by binding the other type variable to the escapable
36893686
// variation of this type.
36903687
auto fn1 = fn2->withExtInfo(fn2->getExtInfo().withNoEscape(false));
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// RUN: %target-swift-frontend -module-name main -typecheck -swift-version 3 %s
2+
// RUN: %target-swift-frontend -module-name main -typecheck -swift-version 4 %s
3+
4+
// These tests are split out to ensure that we run the AST verifier's
5+
// special post-type-checked verifications, which don't currently
6+
// happen if any errors occur anywhere during compilation.
7+
8+
func rdar32239354_1(_ fn: () -> Void) {
9+
var other: (() -> Void) -> Void = { _ in }
10+
11+
withoutActuallyEscaping(fn, do: other)
12+
// Reassign to avoid warning about changing this to a let, since we
13+
// need this to be a var to trigger the original issue.
14+
other = { _ in }
15+
}
16+
17+
func rdar32239354_2(_ fn: () -> Void, other: inout (() -> Void) -> Void) {
18+
withoutActuallyEscaping(fn, do: other)
19+
}
20+
21+
func testVariations(
22+
_ no_escape: () -> (),
23+
_ escape: @escaping () -> (),
24+
_ takesFn: (()->()) -> ()->()
25+
) -> () -> () {
26+
withoutActuallyEscaping(no_escape) { _ in }
27+
withoutActuallyEscaping({}) { _ in }
28+
withoutActuallyEscaping(escape) { _ in }
29+
_ = withoutActuallyEscaping(no_escape, do: takesFn)
30+
_ = withoutActuallyEscaping(escape, do: takesFn)
31+
_ = withoutActuallyEscaping(no_escape) {
32+
return takesFn($0)
33+
}
34+
}

0 commit comments

Comments
 (0)