blob: 94c7e6a2003d9bc06ebef2722431ee0431385a2b [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
// Similarly-abstract generic signatures should share an unsubstituted type
// even in different generic contexts
// CHECK-LABEL: sil {{.*}}1a{{.*}} : $@convention(thin) <T, U> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1 for <T, U>) -> ()
func a<T, U>(_ x: (T) -> U) {}
// CHECK-LABEL: sil {{.*}}1b{{.*}} : $@convention(thin) <T, U> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1 for <U, T>) -> ()
func b<T, U>(_ x: (U) -> T) {}
// CHECK-LABEL: sil {{.*}}1c{{.*}} : $@convention(thin) <T, U, V> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1 for <V, T>, @in_guaranteed U) -> ()
func c<T, U, V>(_ x: (V) -> T, _: U) {}
// CHECK-LABEL: sil {{.*}}003Hca{{.*}} : $@convention(thin) <T> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1 for <T, T>) -> ()
func ç<T>(_ x: (T) -> T) {}
// CHECK-LABEL: sil {{.*}}returnsThrowing{{.*}} : $@convention(thin) <T, U, V> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1, τ_0_2> (@in_guaranteed τ_0_0) -> (@owned @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> (@out τ_0_1, @error Error) for <τ_0_1, τ_0_2>) for <T, U, V>) -> () {
func returnsThrowing<T, U, V>(_ x: (T) -> (U) throws -> V) {}
// ...including unconstrained associated types
protocol P {
associatedtype A
}
// CHECK-LABEL: sil {{.*}}1d{{.*}} : $@convention(thin) <T where T : P> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1 for <T, T.A>) -> ()
func d<T: P>(_ x: (T) -> T.A) {}
// CHECK-LABEL: sil {{.*}}1e{{.*}} : $@convention(thin) <T where T : P> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1 for <T.A, T>) -> ()
func e<T: P>(_ x: (T.A) -> T) {}
// Preserve class constraints, because they're less abstract for layout and
// calling convention purposes than unconstrained types
// CHECK-LABEL: sil {{.*}}1f{{.*}} : $@convention(thin) <T, U where T : AnyObject> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1 where τ_0_0 : _RefCountedObject> (@guaranteed τ_0_0) -> @out τ_0_1 for <T, U>) -> ()
func f<T: AnyObject, U>(_ x: (T) -> U) {}
// CHECK-LABEL: sil {{.*}}1g{{.*}} : $@convention(thin) <T, U where T : AnyObject> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1 where τ_0_1 : _RefCountedObject> (@in_guaranteed τ_0_0) -> @owned τ_0_1 for <U, T>) -> ()
func g<T: AnyObject, U>(_ x: (U) -> T) {}
// CHECK-LABEL: sil {{.*}}1h{{.*}} : $@convention(thin) <T, U where T : AnyObject, U : AnyObject> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1 where τ_0_0 : _RefCountedObject, τ_0_1 : _RefCountedObject> (@guaranteed τ_0_0) -> @owned τ_0_1 for <T, U>) -> ()
func h<T: AnyObject, U: AnyObject>(_ x: (T) -> U) {}
// CHECK-LABEL: sil {{.*}}1i{{.*}} : $@convention(thin) <T, U where T : AnyObject, U : AnyObject> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1 where τ_0_0 : _RefCountedObject, τ_0_1 : _RefCountedObject> (@guaranteed τ_0_0) -> @owned τ_0_1 for <U, T>) -> ()
func i<T: AnyObject, U: AnyObject>(_ x: (U) -> T) {}
// Indirect class constraints
protocol PC: AnyObject { }
// CHECK-LABEL: sil {{.*}}1j{{.*}} : $@convention(thin) <T, U where T : PC> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1 where τ_0_0 : _RefCountedObject> (@guaranteed τ_0_0) -> @out τ_0_1 for <T, U>) -> ()
func j<T: PC, U>(_ x: (T) -> U) {}
// CHECK-LABEL: sil {{.*}}1k{{.*}} : $@convention(thin) <T, U where T : PC> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1 where τ_0_1 : _RefCountedObject> (@in_guaranteed τ_0_0) -> @owned τ_0_1 for <U, T>) -> ()
func k<T: PC, U>(_ x: (U) -> T) {}
// CHECK-LABEL: sil {{.*}}1l{{.*}} : $@convention(thin) <T, U where T : PC, U : PC> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1 where τ_0_0 : _RefCountedObject, τ_0_1 : _RefCountedObject> (@guaranteed τ_0_0) -> @owned τ_0_1 for <T, U>) -> ()
func l<T: PC, U: PC>(_ x: (T) -> U) {}
// CHECK-LABEL: sil {{.*}}1m{{.*}} : $@convention(thin) <T, U where T : PC, U : PC> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1 where τ_0_0 : _RefCountedObject, τ_0_1 : _RefCountedObject> (@guaranteed τ_0_0) -> @owned τ_0_1 for <U, T>) -> ()
func m<T: PC, U: PC>(_ x: (U) -> T) {}
// CHECK-LABEL: sil {{.*}}1n{{.*}} : $@convention(thin) <T where T : P, T : PC> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1 where τ_0_0 : _RefCountedObject> (@guaranteed τ_0_0) -> @out τ_0_1 for <T, T.A>) -> ()
func n<T: P & PC>(_ x: (T) -> T.A) {}
// Superclass constraints
class Base {}
// CHECK-LABEL: sil {{.*}}1o{{.*}} : $@convention(thin) <T, U where T : Base> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1 where τ_0_0 : _RefCountedObject> (@guaranteed τ_0_0) -> @out τ_0_1 for <T, U>) -> ()
func o<T: Base, U> (_ x: (T) -> U) {}
// Indirect constraints by associated type or protocol
protocol PCAO: AnyObject {
associatedtype A
}
protocol POAC {
associatedtype A: AnyObject
}
protocol PCAC: AnyObject {
associatedtype A: AnyObject
}
// CHECK-LABEL: sil {{.*}}1p{{.*}} : $@convention(thin) <T where T : PCAO> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1 where τ_0_0 : _RefCountedObject> (@guaranteed τ_0_0) -> @out τ_0_1 for <T, T.A>) -> ()
func p<T: PCAO> (_ x: (T) -> T.A) {}
// CHECK-LABEL: sil {{.*}}1q{{.*}} : $@convention(thin) <T where T : POAC> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1 where τ_0_1 : _RefCountedObject> (@in_guaranteed τ_0_0) -> @owned τ_0_1 for <T, T.A>) -> ()
func q<T: POAC> (_ x: (T) -> T.A) {}
// CHECK-LABEL: sil {{.*}}1r{{.*}} : $@convention(thin) <T where T : PCAC> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1 where τ_0_0 : _RefCountedObject, τ_0_1 : _RefCountedObject> (@guaranteed τ_0_0) -> @owned τ_0_1 for <T, T.A>) -> ()
func r<T: PCAC> (_ x: (T) -> T.A) {}
// Structural positions
struct S<T, U> {
struct Nested<V> {
struct NesNestedted<W> { }
struct NestedNonGeneric { }
}
struct NestedNonGeneric {
struct NesNestedted<W> { }
struct NestedNonGeneric { }
}
}
// CHECK-LABEL: sil {{.*}}1t{{.*}} : $@convention(thin) <T, U where U : AnyObject> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_1 : _RefCountedObject, τ_0_3 : _RefCountedObject> (S<τ_0_0, τ_0_1>) -> (@out τ_0_2, @owned τ_0_3) for <T, U, T, U>) -> ()
func t<T, U: AnyObject>(_: (S<T, U>) -> (T, U)) {}
// CHECK-LABEL: sil {{.*}}2t2{{.*}} : $@convention(thin) <T, U where U : AnyObject> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1, τ_0_2, τ_0_3, τ_0_4 where τ_0_1 : _RefCountedObject, τ_0_2 : _RefCountedObject, τ_0_4 : _RefCountedObject> (S<τ_0_0, τ_0_1>.Nested<τ_0_2>) -> (@out τ_0_3, @owned τ_0_4) for <T, U, U, T, U>) -> ()
func t2<T, U: AnyObject>(_: (S<T, U>.Nested<U>) -> (T, U)) {}
// CHECK-LABEL: sil {{.*}}2t3{{.*}} : $@convention(thin) <T, U where U : AnyObject> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1, τ_0_2, τ_0_3, τ_0_4, τ_0_5 where τ_0_1 : _RefCountedObject, τ_0_2 : _RefCountedObject, τ_0_5 : _RefCountedObject> (S<τ_0_0, τ_0_1>.Nested<τ_0_2>.NesNestedted<τ_0_3>) -> (@out τ_0_4, @owned τ_0_5) for <T, U, U, T, T, U>) -> ()
func t3<T, U: AnyObject>(_: (S<T, U>.Nested<U>.NesNestedted<T>) -> (T, U)) {}
// CHECK-LABEL: sil {{.*}}2t4{{.*}} : $@convention(thin) <T, U where U : AnyObject> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1, τ_0_2, τ_0_3, τ_0_4 where τ_0_1 : _RefCountedObject, τ_0_2 : _RefCountedObject, τ_0_4 : _RefCountedObject> (S<τ_0_0, τ_0_1>.Nested<τ_0_2>.NestedNonGeneric) -> (@out τ_0_3, @owned τ_0_4) for <T, U, U, T, U>) -> ()
func t4<T, U: AnyObject>(_: (S<T, U>.Nested<U>.NestedNonGeneric) -> (T, U)) {}
// CHECK-LABEL: sil {{.*}}2t5{{.*}} : $@convention(thin) <T, U where U : AnyObject> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_1 : _RefCountedObject, τ_0_3 : _RefCountedObject> (S<τ_0_0, τ_0_1>.NestedNonGeneric) -> (@out τ_0_2, @owned τ_0_3) for <T, U, T, U>) -> ()
func t5<T, U: AnyObject>(_: (S<T, U>.NestedNonGeneric) -> (T, U)) {}
// CHECK-LABEL: sil {{.*}}2t6{{.*}} : $@convention(thin) <T, U where U : AnyObject> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1, τ_0_2, τ_0_3, τ_0_4 where τ_0_1 : _RefCountedObject, τ_0_4 : _RefCountedObject> (S<τ_0_0, τ_0_1>.NestedNonGeneric.NesNestedted<τ_0_2>) -> (@out τ_0_3, @owned τ_0_4) for <T, U, T, T, U>) -> ()
func t6<T, U: AnyObject>(_: (S<T, U>.NestedNonGeneric.NesNestedted<T>) -> (T, U)) {}
// CHECK-LABEL: sil {{.*}}2t7{{.*}} : $@convention(thin) <T, U where U : AnyObject> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_1 : _RefCountedObject, τ_0_3 : _RefCountedObject> (S<τ_0_0, τ_0_1>.NestedNonGeneric.NestedNonGeneric) -> (@out τ_0_2, @owned τ_0_3) for <T, U, T, U>) -> ()
func t7<T, U: AnyObject>(_: (S<T, U>.NestedNonGeneric.NestedNonGeneric) -> (T, U)) {}
// CHECK-LABEL: sil {{.*}}1u{{.*}} : $@convention(thin) <T> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1, τ_0_2> (S<τ_0_0, τ_0_1>) -> @out τ_0_2 for <T, T, T>) -> ()
func u<T>(_: (S<T, T>) -> T) {}
class C<T, U> {}
// CHECK-LABEL: sil {{.*}}1v{{.*}} : $@convention(thin) <T, U where U : AnyObject> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_1 : _RefCountedObject, τ_0_3 : _RefCountedObject> (@guaranteed C<τ_0_0, τ_0_1>) -> (@out τ_0_2, @owned τ_0_3) for <T, U, T, U>) -> ()
func v<T, U: AnyObject>(_: (C<T, U>) -> (T, U)) {}
// CHECK-LABEL: sil {{.*}}1w{{.*}} : $@convention(thin) <T> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1, τ_0_2> (@guaranteed C<τ_0_0, τ_0_1>) -> @out τ_0_2 for <T, T, T>) -> ()
func w<T>(_: (C<T, T>) -> T) {}
// CHECK-LABEL: sil {{.*}}1x{{.*}} : $@convention(thin) <T, U, V where V : C<T, U>> (@noescape @callee_guaranteed @substituted <τ_0_0 where τ_0_0 : _RefCountedObject> (@guaranteed τ_0_0) -> () for <V>) -> ()
func x<T, U, V: C<T, U>>(_: (V) -> Void) {}
// We can't generally lower away protocol constraints
// in nominal type argument positions, because they're necessary for the
// substitutions to be valid, and associated types may influence the ABI of
// the nominal type.
struct SP<T: P> { var x: T.A }
class CP<T: P> { }
// CHECK-LABEL: sil {{.*}}1z{{.*}} : $@convention(thin) <T where T : P> (@noescape @callee_guaranteed @substituted <τ_0_0 where τ_0_0 : P> (@in_guaranteed SP<τ_0_0>) -> () for <T>) -> ()
func z<T: P>(_: (SP<T>) -> Void) {}
struct SCP<T: P, U: CP<T>> {}
// CHECK-LABEL: sil {{.*}}2z2{{.*}} : $@convention(thin) <T, U where T : P, U : CP<T>> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1 where τ_0_0 : P, τ_0_1 : CP<τ_0_0>, τ_0_1 : _NativeClass> (SCP<τ_0_0, τ_0_1>) -> () for <T, U>) -> ()
func z2<T: P, U: CP<T>>(_: (SCP<T, U>) -> Void) {}
// CHECK-LABEL: sil {{.*}}3z2a{{.*}} : $@convention(thin) <T, U where T : AnyObject, T : P, U : CP<T>> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1 where τ_0_0 : _RefCountedObject, τ_0_0 : P, τ_0_1 : CP<τ_0_0>, τ_0_1 : _NativeClass> (SCP<τ_0_0, τ_0_1>) -> () for <T, U>) -> ()
func z2a<T: P & AnyObject, U: CP<T>>(_: (SCP<T, U>) -> Void) {}
// CHECK-LABEL: sil {{.*}}2z3{{.*}} : $@convention(thin) <T, U where T : P, U : CP<T>> (@noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1 where τ_0_0 : _RefCountedObject, τ_0_1 : _RefCountedObject> (S<τ_0_0, τ_0_1>) -> () for <U, U>) -> ()
func z3<T: P, U: CP<T>>(_: (S<U, U>) -> Void) {}
// Opaque types should not be extracted as substituted arguments because they
// aren't freely substitutable.
dynamic func opaqueAny() -> some Any { return C<Int, String>() }
dynamic func opaqueObject() -> some AnyObject { return C<Int, String>() }
// CHECK-LABEL: sil {{.*}}1y{{.*}} : $@convention(thin) (@noescape @callee_guaranteed (@in_guaranteed @_opaqueReturnTypeOf("$s4main9opaqueAnyQryF", 0) {{.*}}) -> @owned @_opaqueReturnTypeOf("$s4main12opaqueObjectQryF", 0) {{.*}}) -> ()
func y(_: (@_opaqueReturnTypeOf("$s4main9opaqueAnyQryF", 0) X) -> (@_opaqueReturnTypeOf("$s4main12opaqueObjectQryF", 0) X)) {}
// Make sure type lowering doesn't choke on override signatures.
class Foo {
func foo() -> Foo { return self }
}
class Bar<T>: Foo {
override func foo() -> Bar<T> { return self }
}