blob: 5bd4898377eb8c2142ebf3f36797ec3164a2e61b [file] [log] [blame]
// RUN: %target-swift-frontend -emit-silgen -disable-availability-checking -module-name main -enable-subst-sil-function-types-for-function-values %s | %FileCheck %s
func generic<T, U>(_ f: @escaping (T) -> U) -> (T) -> U { return f }
// CHECK-LABEL: sil {{.*}}4main{{.*}}11sameGeneric
func sameGeneric<X, Y, Z>(_: X, _: Y, _ f: @escaping (Z) -> Z) -> (Z) -> Z {
// CHECK: bb0({{.*}}, [[F:%[0-9]+]] : @guaranteed $@callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1 for <Z, Z>
// Similarly generic types should be directly substitutable
// CHECK: [[GENERIC:%.*]] = function_ref @{{.*}}4main{{.*}}7generic
// CHECK: [[RET:%.*]] = apply [[GENERIC]]<Z, Z>([[F]])
// CHECK: return [[RET]]
return generic(f)
}
// CHECK-LABEL: sil {{.*}}4main{{.*}}16concreteIndirect
func concreteIndirect(_ f: @escaping (Any) -> Any) -> (Any) -> Any {
// CHECK: bb0([[F:%[0-9]+]] : @guaranteed $@callee_guaranteed (@in_guaranteed Any) -> @out Any)
// Any is passed indirectly, but is a concrete type, so we need to convert
// to the generic abstraction level
// CHECK: [[F2:%.*]] = copy_value [[F]]
// CHECK: [[GENERIC_F:%.*]] = convert_function [[F2]] : {{.*}} to $@callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1 for <Any, Any>
// CHECK: [[GENERIC:%.*]] = function_ref @{{.*}}4main{{.*}}7generic
// CHECK: [[GENERIC_RET:%.*]] = apply [[GENERIC]]<Any, Any>([[GENERIC_F]])
// CHECK: [[RET:%.*]] = convert_function [[GENERIC_RET]] : {{.*}}
// CHECK: return [[RET]]
return generic(f)
}
// CHECK-LABEL: sil {{.*}}4main{{.*}}14concreteDirect
func concreteDirect(_ f: @escaping (Int) -> String) -> (Int) -> String {
// CHECK: bb0([[F:%[0-9]+]] : @guaranteed $@callee_guaranteed (Int) -> @owned String):
// Int and String are passed and returned directly, so we need both
// thunking and conversion to the substituted form
// CHECK: [[F2:%.*]] = copy_value [[F]]
// CHECK: [[REABSTRACT_F:%.*]] = partial_apply {{.*}}([[F2]])
// CHECK: [[GENERIC_F:%.*]] = convert_function [[REABSTRACT_F]] : {{.*}} to $@callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1 for <Int, String>
// CHECK: [[GENERIC:%.*]] = function_ref @{{.*}}4main{{.*}}7generic
// CHECK: [[GENERIC_RET:%.*]] = apply [[GENERIC]]<Int, String>([[GENERIC_F]])
// CHECK: [[REABSTRACT_RET:%.*]] = convert_function [[GENERIC_RET]] : {{.*}}
// CHECK: [[RET:%.*]] = partial_apply {{.*}}([[REABSTRACT_RET]])
// CHECK: return [[RET]]
return generic(f)
}
func genericTakesFunction<T, U>(
_ f: @escaping ((T) -> U) -> (T) -> U
) -> ((T) -> U) -> (T) -> U { return f }
func sameGenericTakesFunction<T>(
_ f: @escaping ((T) -> T) -> (T) -> T
) -> ((T) -> T) -> (T) -> T {
return genericTakesFunction(f)
}
// CHECK-LABEL: sil {{.*}}4main29concreteIndirectTakesFunction
func concreteIndirectTakesFunction(
_ f: @escaping ((Any) -> Any) -> (Any) -> Any
) -> ((Any) -> Any) -> (Any) -> Any {
// CHECK: bb0([[F:%[0-9]+]] : @guaranteed $@callee_guaranteed
// Calling convention matches callee, but the representation of the argument
// to `f` needs to change, so we still have to thunk
// CHECK: [[F2:%.*]] = copy_value [[F]]
// CHECK: [[REABSTRACT_F:%.*]] = partial_apply {{.*}}([[F2]])
// CHECK: [[GENERIC_F:%.*]] = convert_function [[REABSTRACT_F]]
// CHECK: [[GENERIC:%.*]] = function_ref @{{.*}}4main{{.*}}20genericTakesFunction
// CHECK: [[GENERIC_RET:%.*]] = apply [[GENERIC]]<Any, Any>([[GENERIC_F]])
// CHECK: [[REABSTRACT_RET:%.*]] = convert_function [[GENERIC_RET]] : {{.*}}
// CHECK: [[RET:%.*]] = partial_apply {{.*}}([[REABSTRACT_RET]])
// CHECK: return [[RET]]
return genericTakesFunction(f)
}
func concreteDirectTakesFunction(
_ f: @escaping ((Int) -> String) -> (Int) -> String
) -> ((Int) -> String) -> (Int) -> String {
// Int and String are passed and returned directly, so we need both
// thunking and conversion to the substituted form
return genericTakesFunction(f)
}