blob: 1eb5b8608ef3a76f9c03bd5cf15e82ce4999f5ae [file] [log] [blame]
// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -emit-sil -O %s | %FileCheck %s
sil_stage raw
import Builtin
typealias Int = Builtin.Int32
// rdar://problem/28945854: When a nongeneric closure was formed inside a
// generic function, the capture promotion pass would erroneously try to
// apply the generic caller's substitutions to the nongeneric callee, violating
// invariants.
// CHECK-LABEL: sil @_TTSf2i__promotable_box : $@convention(thin) (Builtin.Int32) -> Builtin.Int32
sil @promotable_box : $@convention(thin) (<τ_0_0> { var τ_0_0 } <Int>) -> Int {
entry(%b : $_0_0> { var τ_0_0 } <Int>):
%a = project_box %b : $_0_0> { var τ_0_0 } <Int>, 0
%v = load %a : $*Int
return %v : $Int
}
// CHECK-LABEL: sil @call_promotable_box_from_generic
// CHECK: [[F:%.*]] = function_ref @_TTSf2i__promotable_box
// CHECK: partial_apply [[F]](
sil @call_promotable_box_from_generic : $@convention(thin) <T> (@in T, Int) -> @owned @callee_owned () -> Int {
entry(%0 : $*T, %1 : $Int):
destroy_addr %0 : $*T
%f = function_ref @promotable_box : $@convention(thin) (<τ_0_0> { var τ_0_0 } <Int>) -> Int
%b = alloc_box $_0_0> { var τ_0_0 } <Int>
%a = project_box %b : $_0_0> { var τ_0_0 } <Int>, 0
store %1 to %a : $*Int
%k = partial_apply %f(%b) : $@convention(thin) (<τ_0_0> { var τ_0_0 } <Int>) -> Int
return %k : $@callee_owned () -> Int
}
// Applying the caller's substitutions to a generic closure callee would also
// be disastrous, but it appears that capture promotion currently bails out
// on generic closures. This test is included to ensure there aren't regressions
// if capture promotion is ever generalized to generic closures.
protocol P {}
// TODO: Ought to be promotable, but currently is not.
// rdar://problem/28948735
// CHECK-LABEL: sil @generic_promotable_box
sil @generic_promotable_box : $@convention(thin) <T> (@in T, _0_0> { var τ_0_0 } <Int>) -> Int {
entry(%0 : $*T, %b : $_0_0> { var τ_0_0 } <Int>):
%a = project_box %b : $_0_0> { var τ_0_0 } <Int>, 0
%v = load %a : $*Int
return %v : $Int
}
// CHECK-LABEL: sil @call_generic_promotable_box_from_different_generic
// CHECK: [[F:%.*]] = function_ref @generic_promotable_box
// CHECK: partial_apply [[F]]<U>(
sil @call_generic_promotable_box_from_different_generic : $@convention(thin) <T, U: P> (@in T, @in U, Int) -> @owned @callee_owned (@in U) -> Int {
entry(%0 : $*T, %1 : $*U, %2 : $Int):
destroy_addr %0 : $*T
destroy_addr %1 : $*U
%f = function_ref @generic_promotable_box : $@convention(thin) <V> (@in V, _0_0> { var τ_0_0 } <Int>) -> Int
%b = alloc_box $_0_0> { var τ_0_0 } <Int>
%a = project_box %b : $_0_0> { var τ_0_0 } <Int>, 0
store %2 to %a : $*Int
%k = partial_apply %f<U>(%b) : $@convention(thin) <V> (@in V, _0_0> { var τ_0_0 } <Int>) -> Int
return %k : $@callee_owned (@in U) -> Int
}