Skip to content

Commit fadf5d4

Browse files
committed
MoveOnlyChecker: Look through convert_function of nonescaping closures.
Like a nested partial_apply reabstraction, but without the thunk, these change the representation of the function but can't escape it without breaking the nonescaping closure promotion. rdar://111060678
1 parent 2a06186 commit fadf5d4

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

lib/SILOptimizer/Mandatory/MoveOnlyAddressCheckerUtils.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -909,7 +909,11 @@ static bool findNonEscapingPartialApplyUses(PartialApplyInst *pai,
909909
//
910910
// We have this separately from the other look through sections so that
911911
// we can make it clearer what we are doing here.
912-
isa<PartialApplyInst>(user)) {
912+
isa<PartialApplyInst>(user) ||
913+
// Likewise with convert_function. Any valid function conversion that
914+
// doesn't prevent stack promotion of the closure must retain the
915+
// invariants on its transitive uses.
916+
isa<ConvertFunctionInst>(user)) {
913917
for (auto *use : cast<SingleValueInstruction>(user)->getUses())
914918
worklist.push_back(use);
915919
continue;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: %target-swift-frontend -emit-sil -verify %s
2+
3+
// rdar://111060678
4+
5+
protocol P {
6+
func doStuff() throws
7+
}
8+
9+
struct A: ~Copyable {
10+
let b = B()
11+
12+
consuming func f(_ p: some P) throws -> B {
13+
// Passing the closure here undergoes a SIL-level function conversion
14+
// from the concrete type `() -> Void` to `<T> () throws -> T`.
15+
try b.takeClosure {
16+
try b.takeP(p)
17+
}
18+
return B()
19+
}
20+
}
21+
22+
struct B {
23+
func takeClosure<T>(_ f: () throws -> T) throws -> T { try f() }
24+
func takeP(_: some P) throws {}
25+
}

0 commit comments

Comments
 (0)