1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
|
// RUN: %target-swift-emit-silgen(mock-sdk: %clang-importer-sdk) -import-objc-header %S/Inputs/keypaths_objc.h %s | %FileCheck %s
// RUN: %target-swift-emit-ir(mock-sdk: %clang-importer-sdk) -import-objc-header %S/Inputs/keypaths_objc.h %s
// REQUIRES: objc_interop
import Foundation
struct NonObjC {
var x: Int
var y: NSObject
}
class Foo: NSObject {
@objc var int: Int { fatalError() }
@objc var bar: Bar { fatalError() }
var nonobjc: NonObjC { fatalError() }
@objc(thisIsADifferentName) var differentName: Bar { fatalError() }
@objc subscript(x: Int) -> Foo { return self }
@objc subscript(x: Bar) -> Foo { return self }
@objc dynamic var dyn: String { fatalError() }
}
class Bar: NSObject {
@objc var foo: Foo { fatalError() }
}
// CHECK-LABEL: sil hidden [ossa] @$s13keypaths_objc0B8KeypathsyyF
func objcKeypaths() {
// CHECK: keypath $WritableKeyPath<NonObjC, Int>, (root
_ = \NonObjC.x
// CHECK: keypath $WritableKeyPath<NonObjC, NSObject>, (root
_ = \NonObjC.y
// CHECK: keypath $KeyPath<Foo, Int>, (objc "int"
_ = \Foo.int
// CHECK: keypath $KeyPath<Foo, Bar>, (objc "bar"
_ = \Foo.bar
// CHECK: keypath $KeyPath<Foo, Foo>, (objc "bar.foo"
_ = \Foo.bar.foo
// CHECK: keypath $KeyPath<Foo, Bar>, (objc "bar.foo.bar"
_ = \Foo.bar.foo.bar
// CHECK: keypath $KeyPath<Foo, NonObjC>, (root
_ = \Foo.nonobjc
// CHECK: keypath $KeyPath<Foo, NSObject>, (root
_ = \Foo.bar.foo.nonobjc.y
// CHECK: keypath $KeyPath<Foo, Bar>, (objc "thisIsADifferentName"
_ = \Foo.differentName
}
// CHECK-LABEL: sil hidden [ossa] @$s13keypaths_objc0B18KeypathIdentifiersyyF
func objcKeypathIdentifiers() {
// CHECK: keypath $KeyPath<ObjCFoo, String>, (objc "objcProp"; {{.*}} id #ObjCFoo.objcProp!getter.foreign
_ = \ObjCFoo.objcProp
// CHECK: keypath $KeyPath<Foo, String>, (objc "dyn"; {{.*}} id #Foo.dyn!getter.foreign
_ = \Foo.dyn
// CHECK: keypath $KeyPath<Foo, Int>, (objc "int"; {{.*}} id #Foo.int!getter :
_ = \Foo.int
}
struct X {}
extension NSObject {
var x: X { return X() }
@objc var objc: Int { return 0 }
@objc dynamic var dynamic: Int { return 0 }
}
// CHECK-LABEL: sil hidden [ossa] @{{.*}}nonobjcExtensionOfObjCClass
func nonobjcExtensionOfObjCClass() {
// Should be treated as a statically-dispatch property
// CHECK: keypath $KeyPath<NSObject, X>, ({{.*}} id @
_ = \NSObject.x
// CHECK: keypath $KeyPath<NSObject, Int>, ({{.*}} id #NSObject.objc!getter.foreign
_ = \NSObject.objc
// CHECK: keypath $KeyPath<NSObject, Int>, ({{.*}} id #NSObject.dynamic!getter.foreign
_ = \NSObject.dynamic
}
@objc protocol ObjCProto {
var objcRequirement: Int { get set }
}
// CHECK-LABEL: sil hidden [ossa] @{{.*}}ProtocolRequirement
func objcProtocolRequirement<T: ObjCProto>(_: T) {
// CHECK: keypath {{.*}} id #ObjCProto.objcRequirement!getter.foreign
_ = \T.objcRequirement
// CHECK: keypath {{.*}} id #ObjCProto.objcRequirement!getter.foreign
_ = \ObjCProto.objcRequirement
}
// CHECK-LABEL: sil hidden [ossa] @{{.*}}externalObjCProperty
func externalObjCProperty() {
// Pure ObjC-dispatched properties do not have external descriptors.
// CHECK: keypath $KeyPath<NSObject, String>,
// CHECK-NOT: external #NSObject.description
_ = \NSObject.description
}
func sharedCProperty() {
// CHECK: keypath $WritableKeyPath<c_union, some_struct>
// CHECK-NOT: external #c_union.some_field
let dataKeyPath: WritableKeyPath<c_union, some_struct>? = \c_union.some_field
}
class OverrideFrameworkObjCProperty: A {
override var counter: Int32 {
get { return 0 }
set { }
}
}
func overrideFrameworkObjCProperty() {
let _ = \OverrideFrameworkObjCProperty.counter
}
@dynamicMemberLookup
class DynamicClass<Root> {
init() {}
subscript<T>(dynamicMember member: KeyPath<Root, T>) -> DynamicClass<T> {
fatalError()
}
}
// CHECK-LABEL: sil hidden [ossa] @{{.*}}dynamicMemberLookupSimple
func dynamicMemberLookupSimple(foo: DynamicClass<Foo>, nonobjc: DynamicClass<NonObjC>) {
// CHECK: keypath $KeyPath<Foo, Bar>, (objc "bar"
_ = foo.bar
// CHECK: keypath $KeyPath<Foo, Int>, (objc "int"
_ = foo.int
// CHECK: keypath $KeyPath<Foo, Bar>, (objc "bar"
// CHECK: keypath $KeyPath<Bar, Foo>, (objc "foo"
_ = foo.bar.foo
// CHECK: keypath $KeyPath<Foo, NonObjC>, (root
_ = foo.nonobjc
// CHECK: keypath $KeyPath<Foo, Bar>, (objc "thisIsADifferentName"
_ = foo.differentName
// CHECK: keypath $KeyPath<NonObjC, Int>, (root
_ = nonobjc.x
// CHECK: keypath $KeyPath<NonObjC, NSObject>, (root
_ = nonobjc.y
}
// CHECK-LABEL: sil hidden [ossa] @{{.*}}dynamicMemberLookupNestedKeypaths
func dynamicMemberLookupNestedKeypaths(foo: DynamicClass<Foo>) {
// CHECK: keypath $KeyPath<Foo, Bar>, (objc "bar"
// CHECK: keypath $KeyPath<Bar, Foo>, (objc "foo"
// CHECK: keypath $KeyPath<Foo, Bar>, (objc "bar"
_ = foo.bar.foo.bar
}
// CHECK-LABEL: sil hidden [ossa] @{{.*}}dynamicMemberLookupMixedKeypaths
func dynamicMemberLookupMixedKeypaths(foo: DynamicClass<Foo>) {
// CHECK: keypath $KeyPath<Foo, Bar>, (objc "bar"
// CHECK: keypath $KeyPath<Bar, Foo>, (objc "foo"
// CHECK: keypath $KeyPath<Foo, NonObjC>, (root
// CHECK: keypath $KeyPath<NonObjC, NSObject>, (root
_ = foo.bar.foo.nonobjc.y
}
|