// RUN: %target-swift-frontend -Xllvm -sil-inline-generics -emit-sorted-sil -Xllvm -sil-print-types -emit-sil -enable-spec-devirt -O %s | %FileCheck %s // We used to crash on this when trying to devirtualize t.boo(a, 1), // because it is an "apply" with replacement types that contain // archetypes, and the devirtualizer was not able to handle that // case correctly. // // rdar://19912272 protocol P { associatedtype Node } class C { typealias Node = T.Node func foo(_ n:Node) { } func boo(_ n:Node, s:S) { } } func test1(_ t:C, a: T.Node) { t.boo(a, s:1) } class Base { func foo() { } class func boo() { } } class Derived : Base { override func foo() { } override class func boo() { } } // Check that testDevirt is specialized and uses speculative devirtualization. // CHECK-LABEL: sil shared [noinline] @{{.*}}testDevirt // CHECK: checked_cast_br [exact] CC in %{{.*}} : $CC to CC // CHECK: class_method // CHECK: } @inline(never) public func testDevirt(_ c: CC) -> T? { return c.next() } // Check that the instance method Derived.foo can be devirtualized, because Derived.foo is an internal function, // Derived has no subclasses and it is a WMO compilation. // CHECK-LABEL: sil shared [noinline] @$s22devirt_unbound_generic5test2yyAA7DerivedCyxGlFTf4d_n // CHECK-NOT: class_method // CHECK-NOT: witness_method // CHECK-NOT: apply // CHECK: return // CHECK: end sil function '$s22devirt_unbound_generic5test2yyAA7DerivedCyxGlFTf4d_n' @inline(never) func test2(_ d: Derived) { d.foo() } public func doTest2(_ t:T) { test2(Derived()) } // Check that the class method Derived.boo can be devirtualized, because Derived.boo is an internal function, // Derived has no subclasses and it is a WMO compilation. // CHECK: sil shared [noinline] @$s22devirt_unbound_generic5test3yyAA7DerivedCyxGlFTf4d_n // CHECK-NOT: class_method // CHECK-NOT: witness_method // CHECK-NOT: apply // CHECK: return // CHECK: end sil function '$s22devirt_unbound_generic5test3yyAA7DerivedCyxGlFTf4d_n' @inline(never) func test3(_ d: Derived) { type(of: d).boo() } public func doTest3(_ t:T) { test3(Derived()) } public protocol ProtocolWithAssocType { associatedtype Element } private class CP { var value: Base.Element init(_ v: Base.Element) { value = v } func getCount() -> Int32 { return 1 } } private class Base1: ProtocolWithAssocType { typealias Element = Int32 } private class Base2: ProtocolWithAssocType { typealias Element = Int32 } private class CP2: CP> { init() { super.init(1) } override func getCount() -> Int32 { return 2 } } private class CP3: CP> { init() { super.init(1) } override func getCount() -> Int32 { return 3 } } public class CC { func next() -> CT? { return nil } } public protocol QQ { associatedtype Base: PP } public protocol PP { associatedtype Element } internal class D : CC { override func next() -> DT.Base.Element? { return nil } } public struct S: PP { public typealias Element = Int32 } final public class E: QQ { public typealias Base = S } // Check that c.next() inside test4 gets completely devirtualized. // CHECK-LABEL: sil @{{.*}}test4{{.*}} // CHECK-NOT: class_method // CHECK: return public func test4() -> Int32? { let c: CC = D(); return c.next() } public func test5() -> Int32? { return testDevirt(D()) } // The compiler used to crash on this code, because of // generic types involved in the devirtualization. // // rdar://25891588 // // CHECK-LABEL: sil private [noinline] {{.*}}@{{.*}}test6 // CHECK-NOT: class_method // CHECK-NOT: checked_cast_br // CHECK-NOT: class_method // CHECK: } @inline(never) private func test6(_ c: CP) -> T.Element { return c.value } public func doTest6() { test6(CP(1)) } // CHECK-LABEL: sil private [noinline] @{{.*}}test7 // CHECK-NOT: class_method // CHECK: checked_cast_br // CHECK-NOT: class_method // CHECK: } @inline(never) private func test7(_ c: CP) -> Int32 { return c.getCount() } public func doTest7() { test7(CP2()) }