blob: db98884ed22c41dbf9e4041d62d95eac331646d5 [file] [log] [blame]
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -disable-availability-checking %S/Inputs/specialize_opaque_type_archetypes_2.swift -module-name External -emit-module -emit-module-path %t/External.swiftmodule
// RUN: %target-swift-frontend -disable-availability-checking %S/Inputs/specialize_opaque_type_archetypes_3.swift -enable-library-evolution -module-name External2 -emit-module -emit-module-path %t/External2.swiftmodule
// RUN: %target-swift-frontend -disable-availability-checking %S/Inputs/specialize_opaque_type_archetypes_4.swift -I %t -enable-library-evolution -module-name External3 -emit-module -emit-module-path %t/External3.swiftmodule
// RUN: %target-swift-frontend -disable-availability-checking %S/Inputs/specialize_opaque_type_archetypes_3.swift -I %t -enable-library-evolution -module-name External2 -Osize -emit-module -o - | %target-sil-opt -module-name External2 | %FileCheck --check-prefix=RESILIENT %s
// RUN: %target-swift-frontend -disable-availability-checking -I %t -module-name A -enforce-exclusivity=checked -Osize -emit-sil -sil-verify-all %s | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize
// RUN: %target-swift-frontend -disable-availability-checking -I %t -module-name A -enforce-exclusivity=checked -Osize -emit-sil -sil-verify-all %s | %FileCheck %s
// RUN: %target-swift-frontend -disable-availability-checking -I %t -module-name A -enforce-exclusivity=checked -enable-library-evolution -Osize -emit-sil -sil-verify-all %s | %FileCheck %s
import External
import External2
import External3
public protocol P {
func myValue() -> Int64
}
extension Int64: P {
public func myValue() -> Int64 {
return self
}
}
@inline(never)
func useP<T: P> (_ t: T) {
print(t)
}
public func bar(_ x: Int64) -> some P {
return x
}
public func foo(_ x: Int64) -> some P {
if x > 0 {
return bar(x + 1)
}
return bar(x - 1)
}
@inline(never)
func getInt() -> Int64 {
return 2
}
@inline(never)
func identity<T>(_ t: T) -> T {
return t
}
// CHECK-LABEL: sil @$s1A10testFooBaryyxAA1PRzlF : $@convention(thin) <T where T : P> (@in_guaranteed T) -> () {
// CHECK: bb3([[FOOS_INT:%.*]] : $Builtin.Int64):
// CHECK: [[ID:%.*]] = function_ref @$s1A8identityyxxlFs5Int64V_Tg5 : $@convention(thin) (Int64) -> Int64
// CHECK: [[FOO_RES:%.*]] = struct $Int64 ([[FOOS_INT]] : $Builtin.Int64)
// CHECK: [[ID_RES:%.*]] = apply [[ID]]([[FOO_RES]]) : $@convention(thin) (Int64) -> Int64
// CHECK: [[USEP:%.*]] = function_ref @$s1A4usePyyxAA1PRzlFs5Int64V_Tg5 : $@convention(thin) (Int64) -> ()
// CHECK: %27 = apply [[USEP]]([[ID_RES]]) : $@convention(thin) (Int64) -> ()
// CHECK: %29 = apply [[USEP]]([[FOO_RES]]) : $@convention(thin) (Int64) -> ()
public func testFooBar<T:P>(_ t : T) {
let x = foo(getInt())
useP(identity(x))
useP(x.myValue())
}
struct AddressOnly : P{
var p : P = Int64(1)
func myValue() -> Int64 {
return p.myValue()
}
}
public func addressOnlyFoo() -> some P {
return AddressOnly()
}
// CHECK-LABEL: sil @$s1A21testAddressOnlyFoobaryyF
// CHECK-NOT: return type of
// CHECK: return
public func testAddressOnlyFoobar() {
let x = addressOnlyFoo()
let y = x
useP(x.myValue())
useP(y.myValue())
}
public protocol CP : class {
func myValue() -> Int64
}
class C : CP {
func myValue() -> Int64 {
return 0
}
}
public func returnC() -> some CP {
return C()
}
// CHECK-LABEL: sil @$s1A4useCyyF
// CHECK: [[INT:%.*]] = struct $Int64 (
// CHECK: // function_ref specialized useP<A>(_:)
// CHECK: [[FUN:%.*]] = function_ref @$s1A4usePyyxAA1PRzlFs5Int64V_Tg5
// CHECK: = apply [[FUN]]([[INT]])
public func useC() {
let c = returnC()
useP(c.myValue())
}
// CHECK-LABEL: sil @$s1A11useExternalyyF
// CHECK: // function_ref Int64.myValue2()
// CHECK: [[FUN:%.*]] = function_ref @$ss5Int64V8ExternalE8myValue2AByF
// CHECK: apply [[FUN]]
public func useExternal() {
let e = external()
useP(e.myValue2())
}
// Call to a resilient function should not be specialized.
// CHECK-LABEL: sil @$s1A20useExternalResilientyyF
// CHECK: [[RES:%.*]] = alloc_stack $@_opaqueReturnTypeOf("$s9External217externalResilientQryF", 0)
// CHECK: [[FUN:%.*]] = function_ref @$s9External217externalResilientQryF : $@convention(thin) () -> @out @_opaqueReturnTypeOf("$s9External217externalResilientQryF", 0)
// CHECK: apply [[FUN]]([[RES]])
// CHECK: witness_method
// CHECK: return
public func useExternalResilient() {
let e = externalResilient()
useP(e.myValue3())
}
struct Container {
var x : some P {
get {
return Int64(1)
}
}
}
// CHECK-LABEL: sil @$s1A11usePropertyyyF
// CHECK: [[VAL:%.*]] = struct $Int64
// CHECK: // function_ref specialized useP<A>(_:)
// CHECK: [[FUN:%.*]] = function_ref @$s1A4usePyyxAA1PRzlFs5Int64V_Tg5
// CHECK: apply [[FUN]]([[VAL]])
public func useProperty() {
let p = Container().x
useP(p.myValue())
}
protocol Q {
associatedtype T
func f() -> T
associatedtype T2
func g() -> T2
}
struct S : Q {
func f()->some P { return Int64(1) }
func g()->some CP { return C() }
}
struct Container2 {
var member : S.T
mutating func blah(_ x: S.T) { member = x }
}
class Container3 {
init(member : S.T) {
self.member = member
}
var member : S.T
func blah(_ x: S.T) { member = x }
}
struct Container4 {
var member : S.T2
mutating func blah(_ x: S.T2) { member = x }
}
struct Container5 {
var member : (S.T2, S.T)
mutating func blah(_ x: S.T2, _ y: S.T) { member = (x,y) }
}
struct Pair<T, V> {
var first: T
var second: V
}
// CHECK-LABEL: sil @$s1A10storedPropyyF
// CHECK-NOT: apply
// CHECK: store
// CHECK-NOT: apply
// CHECK: store
// CHECK-NOT: apply
// CHECK: store
// CHECK-NOT: apply
// CHECK: return
public func storedProp() {
var c = Container2(member: S().f())
c.blah(S().f())
var c2 = Container3(member: S().f())
c2.blah(S().f())
var c3 = Container4(member: S().g())
c3.blah(S().g())
var s = S()
var c4 = Container5(member: (s.g(), s.f()))
c4.blah(s.g(), s.f())
}
public func usePair() {
var x = Pair(first: bar(1), second: returnC())
useP(x.first.myValue())
useP(x.second.myValue())
}
struct MyInt64 : ExternalP2 {
var x = Int64(0)
public func myValue3() -> Int64 {
return x + 3
}
}
func nonResilient() -> some ExternalP2 {
return MyInt64()
}
// CHECK-LABEL: sil @$s1A019usePairResilientNonC0yyF : $@convention(thin) () -> ()
// CHECK: alloc_stack $Pair<MyInt64, @_opaqueReturnTypeOf("$s9External217externalResilientQryF", 0)
// CHECK: cond_fail
// CHECK: [[FIRST_MYVALUE3:%.*]] = struct $Int64
// CHECK: [[USEP:%.*]] = function_ref @$s1A4usePyyxAA1PRzlFs5Int64V_Tg5
// CHECK: apply [[USEP]]([[FIRST_MYVALUE3]])
// CHECK: [[MYVALUE_WITNESS:%.*]] = witness_method $@_opaqueReturnTypeOf("$s9External217externalResilientQryF"
// CHECK: [[SECOND_MYVALUE3:%.*]] = apply [[MYVALUE_WITNESS]]
// CHECK: apply [[USEP]]([[SECOND_MYVALUE3]])
// CHECK: return
public func usePairResilientNonResilient() {
var x = Pair(first: nonResilient(), second: externalResilient())
useP(x.first.myValue3())
useP(x.second.myValue3())
}
public protocol P3 {
associatedtype AT
func foo() -> AT
}
public struct Adapter<T: P3>: P3 {
var inner: T
public func foo() -> some P3 {
return inner
}
}
// Don't assert.
// CHECK-LABEL: sil {{.*}} @$s1A7AdapterVyxGAA2P3A2aEP3foo2ATQzyFTW
// CHECK: [[F:%.*]] = function_ref @$s1A7AdapterV3fooQryF
// CHECK: apply [[F]]<Ï„_0_0>(%0, %1) : $@convention(method) <Ï„_0_0 where Ï„_0_0 : P3> (@in_guaranteed Adapter<Ï„_0_0>) -> @out @_opaqueReturnTypeOf("$s1A7AdapterV3fooQryF", 0)
extension P3 {
public func foo() -> some P3 {
return Adapter(inner: self)
}
}
// We should specialize the opaque type because the resilient function is
// inlineable.
// CHECK-LABEL: sil @$s1A21useExternalResilient2yyF : $@convention(thin) () -> ()
// CHECK: [[RES:%.*]] = alloc_stack $Int64
// CHECK: [[FUN:%.*]] = function_ref @$s9External226inlinableExternalResilientQryF : $@convention(thin) () -> @out @_opaqueReturnTypeOf("$s9External226inlinableExternalResilientQryF", 0)
// CHECK: [[RES2:%.*]] = unchecked_addr_cast [[RES]] : $*Int64 to $*@_opaqueReturnTypeOf("$s9External226inlinableExternalResilientQryF", 0)
// CHECK: apply [[FUN]]([[RES2]])
// CHECK: return
public func useExternalResilient2() {
let e = inlinableExternalResilient()
useP(e.myValue3())
}
// In this case we should only 'peel' one layer of opaque archetypes.
// CHECK-LABEL: sil @$s1A21useExternalResilient3yyF
// CHECK: [[RES:%.*]] = alloc_stack $@_opaqueReturnTypeOf("$s9External217externalResilientQryF", 0)
// CHECK: [[FUN:%.*]] = function_ref @$s9External3031inlinableExternalResilientCallsD0QryF : $@convention(thin) () -> @out @_opaqueReturnTypeOf("$s9External3031inlinableExternalResilientCallsD0QryF", 0)
// CHECK: [[RES2:%.*]] = unchecked_addr_cast [[RES]] : $*@_opaqueReturnTypeOf("$s9External217externalResilientQryF", 0){{.*}}to $*@_opaqueReturnTypeOf("$s9External3031inlinableExternalResilientCallsD0QryF", 0)
// CHECK: apply [[FUN]]([[RES2]])
public func useExternalResilient3() {
let e = inlinableExternalResilientCallsResilient()
useP(e.myValue3())
}
// Check that we can look throught two layers of inlinable resilient functions.
// CHECK-LABEL: sil @$s1A21useExternalResilient4yyF
// CHECK: [[RES:%.*]] = alloc_stack $Int64
// CHECK: [[FUN:%.*]] = function_ref @$s9External3040inlinableExternalResilientCallsInlinablecD0QryF : $@convention(thin) () -> @out @_opaqueReturnTypeOf("$s9External3040inlinableExternalResilientCallsInlinablecD0QryF", 0)
// CHECK: [[RES2:%.*]] = unchecked_addr_cast [[RES]] : $*Int64 to $*@_opaqueReturnTypeOf("$s9External3040inlinableExternalResilientCallsInlinablecD0QryF", 0)
// CHECK: apply [[FUN]]([[RES2]])
public func useExternalResilient4() {
let e = inlinableExternalResilientCallsInlinableExternalResilient()
useP(e.myValue3())
}
// CHECK-LABEL: sil @$s1A18testStoredPropertyyyF
// CHECK: [[CONTAINER_INIT_FUN:%.*]] = function_ref @$s8External0A9ContainerVACycfC
// CHECK: [[CONTAINER:%.*]] = apply [[CONTAINER_INIT_FUN]]
// CHECK: [[RES:%.*]] = alloc_stack $Int64
// CHECK: [[COMPUTED_PROP:%.*]] = function_ref @$s8External0A9ContainerV16computedPropertyQrvg
// CHECK: [[RES2:%.*]] = unchecked_addr_cast [[RES]] : $*Int64 to $*@_opaqueReturnTypeOf("$s8External0A9ContainerV16computedPropertyQrvp", 0)
// CHECK: apply [[COMPUTED_PROP]]([[RES2]], [[CONTAINER]])
// CHECK: [[MYVALUE:%.*]] = function_ref @$ss5Int64V8ExternalE8myValue2AByF : $@convention(method) (Int64) -> Int64
// CHECK: apply [[MYVALUE]]
public func testStoredProperty() {
let c = ExternalContainer()
useP(c.computedProperty.myValue2())
}
// CHECK-LABEL: sil @$s1A21testResilientPropertyyyF
// CHECK: [[CONTAINER:%.*]] = alloc_stack $ResilientContainer
// CHECK: [[RES:%.*]] = alloc_stack $@_opaqueReturnTypeOf("$s9External218ResilientContainerV16computedPropertyQrvp", 0)
// CHECK: [[FUN:%.*]] = function_ref @$s9External218ResilientContainerV16computedPropertyQrvg
// CHECK: apply [[FUN]]([[RES]], [[CONTAINER]])
public func testResilientProperty() {
let r = ResilientContainer()
useP(r.computedProperty.myValue3())
}
// CHECK-LABEL: sil @$s1A30testResilientInlinablePropertyyyF
// CHECK: [[CONTAINER:%.*]] = alloc_stack $ResilientContainer
// CHECK: [[RES:%.*]] = alloc_stack $Int64
// CHECK: [[FUN:%.*]] = function_ref @$s9External218ResilientContainerV18inlineablePropertyQrvg
// CHECK: [[RES2:%.*]] = unchecked_addr_cast [[RES]] : $*Int64 to $*@_opaqueReturnTypeOf("$s9External218ResilientContainerV18inlineablePropertyQrvp", 0)
// CHECK: apply [[FUN]]([[RES2]], [[CONTAINER]])
public func testResilientInlinableProperty() {
let r = ResilientContainer()
useP(r.inlineableProperty.myValue3())
}
// CHECK-LABEL: sil @$s1A31testResilientInlinableProperty3yyF
// CHECK: [[CONTAINER:%.*]] = alloc_stack $ResilientContainer
// CHECK: [[RES:%.*]] = alloc_stack $Int64
// CHECK: [[FUN:%.*]] = function_ref @$s9External218ResilientContainerV19inlineableProperty2Qrvg
// CHECK: [[RES2:%.*]] = unchecked_addr_cast [[RES]] : $*Int64 to $*@_opaqueReturnTypeOf("$s9External218ResilientContainerV19inlineableProperty2Qrvp", 0)
// CHECK: apply [[FUN]]([[RES2]], [[CONTAINER]])
public func testResilientInlinableProperty3() {
let r = ResilientContainer()
useP(r.inlineableProperty2.myValue3())
}
// CHECK-LABEL: sil @$s1A22testResilientProperty2yyF
// CHECK: [[CONTAINER:%.*]] = alloc_stack $ResilientContainer2
// CHECK: [[RES:%.*]] = alloc_stack $@_opaqueReturnTypeOf("$s9External319ResilientContainer2V16computedPropertyQrvp", 0)
// CHECK: [[FUN:%.*]] = function_ref @$s9External319ResilientContainer2V16computedPropertyQrvg
// CHECK: apply [[FUN]]([[RES]], [[CONTAINER]])
public func testResilientProperty2() {
let r = ResilientContainer2()
useP(r.computedProperty.myValue3())
}
// The inlinable property recursively calls an resilient property 'peel' one layer of opaque archetypes.
// CHECK-LABEL: sil @$s1A31testResilientInlinableProperty2yyF
// CHECK: [[CONTAINER:%.*]] = alloc_stack $ResilientContainer2
// CHECK: [[RES:%.*]] = alloc_stack $@_opaqueReturnTypeOf("$s9External218ResilientContainerV16computedPropertyQrvp", 0)
// CHECK: [[FUN:%.*]] = function_ref @$s9External319ResilientContainer2V18inlineablePropertyQrvg
// CHECK: [[RES2:%.*]] = unchecked_addr_cast [[RES]] : $*@_opaqueReturnTypeOf("$s9External218ResilientContainerV16computedPropertyQrvp", 0){{.*}}to $*@_opaqueReturnTypeOf("$s9External319ResilientContainer2V18inlineablePropertyQrvp", 0)
// CHECK: apply [[FUN]]([[RES2]], [[CONTAINER]])
public func testResilientInlinableProperty2() {
let r = ResilientContainer2()
useP(r.inlineableProperty.myValue3())
}
// CHECK-LABEL: sil @$s1A035testResilientInlinablePropertyCallsbC0yyF : $@convention(thin) () -> () {
// CHECK: [[CONTAINTER:%.*]] = alloc_stack $ResilientContainer2
// CHECK: [[RES:%.*]] = alloc_stack $Int64
// CHECK: [[FUN:%.*]] = function_ref @$s9External319ResilientContainer2V023inlineablePropertyCallsB10InlineableQrvg
// CHECK: [[RES2:%.*]] = unchecked_addr_cast [[RES]] : $*Int64 to $*@_opaqueReturnTypeOf("$s9External319ResilientContainer2V023inlineablePropertyCallsB10InlineableQrvp", 0)
// CHECK: apply [[FUN]]([[RES2]], [[CONTAINTER]])
public func testResilientInlinablePropertyCallsResilientInlinable() {
let r = ResilientContainer2()
useP(r.inlineablePropertyCallsResilientInlineable.myValue3())
}
// RESILIENT-LABEL: sil [serialized] [canonical] @$s9External218ResilientContainerV17inlineableContextyyF
// RESILIENT: [[RES:%.*]] = alloc_stack $@_opaqueReturnTypeOf("$s9External218ResilientContainerV16computedPropertyQrvp", 0)
// RESILIENT: [[FUN:%.*]] = function_ref @$s9External218ResilientContainerV16computedPropertyQrvg
// RESILIENT: apply [[FUN]]([[RES]], %0)
public protocol P4 {
associatedtype AT
func foo(_ x: Int64) -> AT
func test()
}
struct PA : P4 {
func foo(_ x: Int64) -> some P {
return Int64(x)
}
}
// CHECK-LABEL: sil private [transparent] [thunk] @$s1A2PAVAA2P4A2aDP4testyyFTW
// CHECK: [[V:%.*]] = load %0 : $*PA
// CHECK: [[F:%.*]] = function_ref @$s1A2PAV4testyyF
// CHECK: apply [[F]]([[V]])
// CHECK-64-LABEL: sil hidden @$s1A2PAV4testyyF : $@convention(method) (PA) -> ()
// CHECK-64: [[V:%.*]] = integer_literal $Builtin.Int64, 5
// CHECK-64: [[I:%.*]] = struct $Int64 ([[V]] : $Builtin.Int64)
// CHECK-64: [[F:%.*]] = function_ref @$s1A4usePyyxAA1PRzlFs5Int64V_Tg5
// CHECK-64: apply [[F]]([[I]]) : $@convention(thin) (Int64) -> ()
// CHECK-64: apply [[F]]([[I]]) : $@convention(thin) (Int64) -> ()
@inline(never)
func testIt<T>(cl: (Int64) throws -> T) {
do {
print(try cl(5))
} catch (_) {}
}
// CHECK-LABEL: sil shared [noinline] @$s1A16testPartialApplyyyxAA2P4RzlFAA2PAV_Tg5
// CHECK: [[PA:%.*]] = alloc_stack $PA
// CHECK: store %0 to [[PA]] : $*PA
// CHECK: [[F:%.*]] = function_ref @$s1A2PAVAA2P4A2aDP3fooy2ATQzs5Int64VFTW : $@convention(witness_method: P4) (Int64, @in_guaranteed PA) -> @out @_opaqueReturnTypeOf("$s1A2PAV3fooyQrs5Int64VF", 0)
// CHECK: [[C:%.*]] = partial_apply [callee_guaranteed] [[F]]([[PA]]) : $@convention(witness_method: P4) (Int64, @in_guaranteed PA) -> @out @_opaqueReturnTypeOf("$s1A2PAV3fooyQrs5Int64VF", 0)
// CHECK: convert_function [[C]] : $@callee_guaranteed (Int64) -> @out @_opaqueReturnTypeOf("$s1A2PAV3fooyQrs5Int64VF", {{.*}} to $@callee_guaranteed (Int64) -> (@out Int64, @error Error)
@inline(never)
func testPartialApply<T: P4>(_ t: T) {
let fun = t.foo
testIt(cl: fun)
print(fun(5))
}
public func testPartialApply() {
testPartialApply(PA())
}
struct Trivial<T> {
var x : Int64
}
func createTrivial<T>(_ t: T) -> Trivial<T> {
return Trivial<T>(x: 1)
}
// CHECK: sil @$s1A11testTrivialyyF : $@convention(thin) () -> ()
// CHECK: %0 = integer_literal $Builtin.Int64, 1
// CHECK: %1 = struct $Int64 (%0 : $Builtin.Int64)
// CHECK: %2 = function_ref @$s1A4usePyyxAA1PRzlFs5Int64V_Tg5 : $@convention(thin) (Int64) -> ()
// CHECK: %3 = apply %2(%1)
public func testTrivial() {
let s = bar(10)
let t = createTrivial(s)
useP(t.x)
}
func createTuple<T>(_ t: T) -> (T,T) {
return (t, t)
}
// CHECK: sil @$s1A9testTupleyyF
// CHECK: [[I:%.*]] = integer_literal $Builtin.Int64, 10
// CHECK: [[I2:%.*]] = struct $Int64 ([[I]] : $Builtin.Int64)
// CHECK: [[F:%.*]] = function_ref @$s1A4usePyyxAA1PRzlFs5Int64V_Tg5 : $@convention(thin) (Int64) -> ()
// CHECK: apply [[F]]([[I2]]) : $@convention(thin) (Int64) -> ()
// CHECK: apply [[F]]([[I2]]) : $@convention(thin) (Int64) -> ()
public func testTuple() {
let s = bar(10)
let t = createTuple(s)
useP(t.0)
useP(t.1)
}
extension PA {
func test() {
var p = (foo, foo)
useP(p.0(5))
useP(p.1(5))
}
}
public struct Foo {
var id : Int = 0
var p : Int64 = 1
}
struct Test : RandomAccessCollection {
struct Index : Comparable, Hashable {
var identifier: AnyHashable?
var offset: Int
static func < (lhs: Index, rhs: Index) -> Bool {
return lhs.offset < rhs.offset
}
func hash(into hasher: inout Hasher) {
hasher.combine(identifier)
hasher.combine(offset)
}
}
let foos: [Foo]
let ids: [AnyHashable]
init(foos: [Foo]) {
self.foos = foos
self.ids = foos.map { $0.id }
}
func _index(atOffset n: Int) -> Index {
return Index(identifier: ids.isEmpty ? nil : ids[n], offset: n)
}
var startIndex: Index {
return _index(atOffset: 0)
}
var endIndex: Index {
return Index(identifier: nil, offset: ids.endIndex)
}
func index(after i: Index) -> Index {
return _index(atOffset: i.offset + 1)
}
func index(before i: Index) -> Index {
return _index(atOffset: i.offset - 1)
}
func distance(from start: Index, to end: Index) -> Int {
return end.offset - start.offset
}
func index(_ i: Index, offsetBy n: Int) -> Index {
return _index(atOffset: i.offset + n)
}
subscript(i: Index) -> some P {
return foos[i.offset].p
}
}
@inline(never)
func useAbstractFunction<T: P>(_ fn: (Int64) -> T) {}
public func testThinToThick() {
useAbstractFunction(bar)
}