blob: dccb37cc8d1985c37621e024b44d8ffaa835713c [file] [log] [blame]
// RUN: %target-swift-emit-silgen -enable-sil-ownership %s | %FileCheck %s
class A {}
class B {}
protocol P {}
protocol Q {}
// CHECK-LABEL: sil hidden @{{.*}}loadable
func loadable(readonly: A, writable: inout A,
value: B,
kp: KeyPath<A, B>,
wkp: WritableKeyPath<A, B>,
rkp: ReferenceWritableKeyPath<A, B>) {
// CHECK: [[ROOT_TMP:%.*]] = alloc_stack $A
// CHECK: [[ROOT_COPY:%.*]] = copy_value %0
// CHECK: store [[ROOT_COPY]] to [init] [[ROOT_TMP]]
// CHECK: [[KP_COPY:%.*]] = copy_value %3
// CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}_projectKeyPathReadOnly
// CHECK: [[BORROWED_KP_COPY:%.*]] = begin_borrow [[KP_COPY]]
// CHECK: [[RESULT_TMP:%.*]] = alloc_stack $B
// CHECK: apply [[PROJECT]]<A, B>([[RESULT_TMP]], [[ROOT_TMP]], [[BORROWED_KP_COPY]])
// CHECK: [[RESULT:%.*]] = load [take] [[RESULT_TMP]]
// CHECK: destroy_value [[RESULT]]
_ = readonly[keyPath: kp]
_ = writable[keyPath: kp]
_ = readonly[keyPath: wkp]
// CHECK: function_ref @{{.*}}_projectKeyPathReadOnly
_ = writable[keyPath: wkp]
// CHECK: function_ref @{{.*}}_projectKeyPathReadOnly
_ = readonly[keyPath: rkp]
// CHECK: function_ref @{{.*}}_projectKeyPathReadOnly
_ = writable[keyPath: rkp]
// CHECK: function_ref @{{.*}}_projectKeyPathWritable
writable[keyPath: wkp] = value
// CHECK: function_ref @{{.*}}_projectKeyPathReferenceWritable
readonly[keyPath: rkp] = value
// CHECK: function_ref @{{.*}}_projectKeyPathReferenceWritable
writable[keyPath: rkp] = value
}
// CHECK-LABEL: sil hidden @{{.*}}addressOnly
func addressOnly(readonly: P, writable: inout P,
value: Q,
kp: KeyPath<P, Q>,
wkp: WritableKeyPath<P, Q>,
rkp: ReferenceWritableKeyPath<P, Q>) {
// CHECK: function_ref @{{.*}}_projectKeyPathReadOnly
_ = readonly[keyPath: kp]
// CHECK: function_ref @{{.*}}_projectKeyPathReadOnly
_ = writable[keyPath: kp]
// CHECK: function_ref @{{.*}}_projectKeyPathReadOnly
_ = readonly[keyPath: wkp]
// CHECK: function_ref @{{.*}}_projectKeyPathReadOnly
_ = writable[keyPath: wkp]
// CHECK: function_ref @{{.*}}_projectKeyPathReadOnly
_ = readonly[keyPath: rkp]
// CHECK: function_ref @{{.*}}_projectKeyPathReadOnly
_ = writable[keyPath: rkp]
// CHECK: function_ref @{{.*}}_projectKeyPathWritable
writable[keyPath: wkp] = value
// CHECK: function_ref @{{.*}}_projectKeyPathReferenceWritable
readonly[keyPath: rkp] = value
// CHECK: function_ref @{{.*}}_projectKeyPathReferenceWritable
writable[keyPath: rkp] = value
}
// CHECK-LABEL: sil hidden @{{.*}}reabstracted
func reabstracted(readonly: @escaping () -> (),
writable: inout () -> (),
value: @escaping (A) -> B,
kp: KeyPath<() -> (), (A) -> B>,
wkp: WritableKeyPath<() -> (), (A) -> B>,
rkp: ReferenceWritableKeyPath<() -> (), (A) -> B>) {
// CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}_projectKeyPathReadOnly
_ = readonly[keyPath: kp]
// CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}_projectKeyPathReadOnly
_ = writable[keyPath: kp]
// CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}_projectKeyPathReadOnly
_ = readonly[keyPath: wkp]
// CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}_projectKeyPathReadOnly
_ = writable[keyPath: wkp]
// CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}_projectKeyPathReadOnly
_ = readonly[keyPath: rkp]
// CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}_projectKeyPathReadOnly
_ = writable[keyPath: rkp]
// CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}_projectKeyPathWritable
writable[keyPath: wkp] = value
// CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}_projectKeyPathReferenceWritable
readonly[keyPath: rkp] = value
// CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}_projectKeyPathReferenceWritable
writable[keyPath: rkp] = value
}
// CHECK-LABEL: sil hidden @{{.*}}partial
func partial<A>(valueA: A,
valueB: Int,
pkpA: PartialKeyPath<A>,
pkpB: PartialKeyPath<Int>,
akp: AnyKeyPath) {
// CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}projectKeyPathAny
// CHECK: apply [[PROJECT]]<A>
_ = valueA[keyPath: akp]
// CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}projectKeyPathPartial
// CHECK: apply [[PROJECT]]<A>
_ = valueA[keyPath: pkpA]
// CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}projectKeyPathAny
// CHECK: apply [[PROJECT]]<Int>
_ = valueB[keyPath: akp]
// CHECK: [[PROJECT:%.*]] = function_ref @{{.*}}projectKeyPathPartial
// CHECK: apply [[PROJECT]]<Int>
_ = valueB[keyPath: pkpB]
}
extension Int {
var b: Int { get { return 0 } set { } }
var u: Int { get { return 0 } set { } }
var tt: Int { get { return 0 } set { } }
}
// CHECK-LABEL: sil hidden @{{.*}}writebackNesting
func writebackNesting(x: inout Int,
y: WritableKeyPath<Int, Int>,
z: WritableKeyPath<Int, Int>,
w: Int) -> Int {
// -- get 'b'
// CHECK: function_ref @$sSi19keypath_applicationE1bSivg
// -- apply keypath y
// CHECK: [[PROJECT_FN:%.*]] = function_ref @{{.*}}_projectKeyPathWritable
// CHECK: [[PROJECT_RET:%.*]] = apply [[PROJECT_FN]]
// CHECK: ({{%.*}}, [[OWNER_Y:%.*]]) = destructure_tuple [[PROJECT_RET]]
// -- get 'u'
// CHECK: function_ref @$sSi19keypath_applicationE1uSivg
// -- apply keypath z
// CHECK: [[PROJECT_FN:%.*]] = function_ref @{{.*}}_projectKeyPathWritable
// CHECK: [[PROJECT_RET:%.*]] = apply [[PROJECT_FN]]
// CHECK: ({{%.*}}, [[OWNER_Z:%.*]]) = destructure_tuple [[PROJECT_RET]]
// -- set 'tt'
// CHECK: function_ref @$sSi19keypath_applicationE2ttSivs
// -- destroy owner for keypath projection z
// CHECK: destroy_value [[OWNER_Z]]
// -- set 'u'
// CHECK: function_ref @$sSi19keypath_applicationE1uSivs
// -- destroy owner for keypath projection y
// CHECK: destroy_value [[OWNER_Y]]
// -- set 'b'
// CHECK: function_ref @$sSi19keypath_applicationE1bSivs
x.b[keyPath: y].u[keyPath: z].tt = w
}