Skip to content

Commit 8b45b5a

Browse files
Merge pull request #28805 from aschwaighofer/closure_lifetime_fixup_undef_fix
ClosureLifetimeFixup: Handle undef partial_apply arguments gracefully
2 parents 6d8e5f1 + a78bb3d commit 8b45b5a

File tree

3 files changed

+37
-1
lines changed

3 files changed

+37
-1
lines changed

lib/SILOptimizer/Utils/InstOptUtils.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1020,7 +1020,7 @@ void swift::releasePartialApplyCapturedArg(SILBuilder &builder, SILLocation loc,
10201020
// possible for that value.
10211021

10221022
// If we have qualified ownership, we should just emit a destroy value.
1023-
if (arg->getFunction()->hasOwnership()) {
1023+
if (builder.getFunction().hasOwnership()) {
10241024
callbacks.createdNewInst(builder.createDestroyValue(loc, arg));
10251025
return;
10261026
}

test/SILOptimizer/closure-lifetime-fixup.sil

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,3 +155,26 @@ bb1:
155155
%86 = tuple ()
156156
return %86 : $()
157157
}
158+
159+
sil [ossa] @closureImpl : $@convention(thin) (@guaranteed Klass, @guaranteed Klass) -> Bool
160+
sil [ossa] @useClosure : $@convention(thin) (@noescape @callee_guaranteed () -> Bool) -> ()
161+
162+
// Don't crash.
163+
// CHECK-LABEL: sil hidden [ossa] @testUndefined
164+
// CHECK: [[PA:%.*]] = partial_apply [callee_guaranteed] [on_stack]
165+
// CHECK: mark_dependence
166+
// CHECK: mark_dependence
167+
// CHECK: dealloc_stack [[PA]] : $@noescape @callee_guaranteed () -> Bool
168+
// CHECK: destroy_value
169+
sil hidden [ossa] @testUndefined : $@convention(method) (@guaranteed Klass, @guaranteed Klass) -> () {
170+
bb0(%0 : @guaranteed $Klass, %1 : @guaranteed $Klass):
171+
%4 = function_ref @closureImpl : $@convention(thin) (@guaranteed Klass, @guaranteed Klass) -> Bool
172+
%5 = copy_value %1 : $Klass
173+
%6 = partial_apply [callee_guaranteed] %4(%5, undef) : $@convention(thin) (@guaranteed Klass, @guaranteed Klass) -> Bool
174+
%7 = convert_escape_to_noescape [not_guaranteed] %6 : $@callee_guaranteed () -> Bool to $@noescape @callee_guaranteed () -> Bool
175+
%21 = function_ref @useClosure : $@convention(thin) (@noescape @callee_guaranteed () -> Bool) -> ()
176+
%22 = apply %21(%7) : $@convention(thin) (@noescape @callee_guaranteed () -> Bool) -> ()
177+
destroy_value %6 : $@callee_guaranteed () -> Bool
178+
%42 = tuple ()
179+
return %42 : $()
180+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: not %target-swift-frontend %s -sil-verify-all -c 2>&1 | %FileCheck %s
2+
3+
// Report the error but don't crash.
4+
// CHECK: error: closure captures 'stringList' before it is declared
5+
6+
class TestUndefined {
7+
private var stringList: [String]!
8+
9+
func dontCrash(strings: [String]) {
10+
assert(stringList.allSatisfy({ $0 == stringList.first!}))
11+
let stringList = strings.filter({ $0 == "a" })
12+
}
13+
}

0 commit comments

Comments
 (0)