blob: a510e8f6283e6bd7762967db73528dce3316b8e0 [file] [log] [blame]
// RUN: %target-swift-frontend -Xllvm -sil-inline-generics -emit-sorted-sil -emit-sil -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<T:P> {
typealias Node = T.Node
func foo(_ n:Node) {
}
func boo<S>(_ n:Node, s:S) {
}
}
func test1<T>(_ t:C<T>, a: T.Node) {
t.boo(a, s:1)
}
class Base<T> {
func foo() {
}
class func boo() {
}
}
class Derived<T> : Base<T> {
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<Int32> to $CC<Int32>
// CHECK: class_method
// CHECK: }
@inline(never)
public func testDevirt<T>(_ c: CC<T>) -> T? {
return c.next()
}
// Check that the instance method Derived<T>.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<T>(_ d: Derived<T>) {
d.foo()
}
public func doTest2<T>(_ t:T) {
test2(Derived<T>())
}
// Check that the class method Derived<T>.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<T>(_ d: Derived<T>) {
type(of: d).boo()
}
public func doTest3<T>(_ t:T) {
test3(Derived<T>())
}
public protocol ProtocolWithAssocType {
associatedtype Element
}
private class CP<Base: ProtocolWithAssocType> {
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<T>: ProtocolWithAssocType {
typealias Element = Int32
}
private class CP2: CP<Base2<Int>> {
init() {
super.init(1)
}
override func getCount() -> Int32 {
return 2
}
}
private class CP3: CP<Base2<Int>> {
init() {
super.init(1)
}
override func getCount() -> Int32 {
return 3
}
}
public class CC<CT> {
func next() -> CT? {
return nil
}
}
public protocol QQ {
associatedtype Base: PP
}
public protocol PP {
associatedtype Element
}
internal class D<DT: QQ> : CC<DT.Base.Element> {
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<Int32> = D<E>();
return c.next()
}
public func test5() -> Int32? {
return testDevirt(D<E>())
}
// 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<T: ProtocolWithAssocType>(_ c: CP<T>) -> T.Element {
return c.value
}
public func doTest6() {
test6(CP<Base1>(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<T: ProtocolWithAssocType>(_ c: CP<T>) -> Int32 {
return c.getCount()
}
public func doTest7() {
test7(CP2())
}