| // 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 |
| } |