blob: e0550d096d1c446788983bf8c3d35a9b1e9cd492 [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 @_T014promotable_boxTf2i_n : $@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 @_T014promotable_boxTf2i_n
// 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
}
protocol P {}
// CHECK-LABEL: sil @_T022generic_promotable_boxTf2ni_n : $@convention(thin) <T> (@in T, Builtin.Int32) -> Builtin.Int32
// CHECK: bb0(%0 : $*T, %1 : $Builtin.Int32):
// CHECK-NEXT: return %1 : $Builtin.Int32
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: bb0(%0 : $*T, %1 : $*U, %2 : $Builtin.Int32):
// CHECK-NEXT: destroy_addr %0 : $*T
// CHECK-NEXT: destroy_addr %1 : $*U
// CHECK: [[F:%.*]] = function_ref @_T022generic_promotable_boxTf2ni_n : $@convention(thin) <τ_0_0> (@in τ_0_0, Builtin.Int32) -> Builtin.Int32
// CHECK-NEXT: [[CLOSURE:%.*]] = partial_apply [[F]]<U>(%2)
// CHECK-NEXT: return [[CLOSURE]]
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
}