// RUN: %target-swift-frontend -enable-experimental-keypaths -emit-silgen %s | %FileCheck %s // REQUIRES: PTRSIZE=64 struct S { var x: T let y: String var z: C var computed: C { fatalError() } var observed: C { didSet { fatalError() } } var reabstracted: () -> () } class C { final var x: T final let y: String final var z: S var nonfinal: S var computed: S { fatalError() } var observed: S { didSet { fatalError() } } final var reabstracted: () -> () init() { fatalError() } } protocol P { var x: Int { get } var y: String { get set } } // CHECK-LABEL: sil hidden @{{.*}}storedProperties func storedProperties(_: T) { // CHECK: keypath $WritableKeyPath, T>, <τ_0_0> (root $S<τ_0_0>; stored_property #S.x : $τ_0_0) _ = #keyPath2(S, .x) // CHECK: keypath $KeyPath, String>, <τ_0_0> (root $S<τ_0_0>; stored_property #S.y : $String) _ = #keyPath2(S, .y) // CHECK: keypath $ReferenceWritableKeyPath, T>, <τ_0_0> (root $S<τ_0_0>; stored_property #S.z : $C<τ_0_0>; stored_property #C.x : $τ_0_0) _ = #keyPath2(S, .z.x) // CHECK: keypath $ReferenceWritableKeyPath, T>, <τ_0_0> (root $C<τ_0_0>; stored_property #C.x : $τ_0_0) _ = #keyPath2(C, .x) // CHECK: keypath $KeyPath, String>, <τ_0_0> (root $C<τ_0_0>; stored_property #C.y : $String) _ = #keyPath2(C, .y) // CHECK: keypath $ReferenceWritableKeyPath, T>, <τ_0_0> (root $C<τ_0_0>; stored_property #C.z : $S<τ_0_0>; stored_property #S.x : $τ_0_0) _ = #keyPath2(C, .z.x) // CHECK: keypath $KeyPath, String>, <τ_0_0> (root $C<τ_0_0>; stored_property #C.z : $S<τ_0_0>; stored_property #S.z : $C<τ_0_0>; stored_property #C.y : $String) _ = #keyPath2(C, .z.z.y) } // CHECK-LABEL: sil hidden @{{.*}}computedProperties func computedProperties(_: T) { // CHECK: keypath $ReferenceWritableKeyPath, S>, <τ_0_0 where τ_0_0 : P> ( // CHECK-SAME: root $C<τ_0_0>; // CHECK-SAME: settable_property $S<τ_0_0>, // CHECK-SAME: id #C.nonfinal!getter.1 : (C) -> () -> S, // CHECK-SAME: getter @_T08keypaths1CC8nonfinalAA1SVyxGvTK : $@convention(thin) <τ_0_0> (@in C<τ_0_0>, @thick C<τ_0_0>.Type) -> @out S<τ_0_0>, // CHECK-SAME: setter @_T08keypaths1CC8nonfinalAA1SVyxGvTk : $@convention(thin) <τ_0_0> (@in S<τ_0_0>, @in C<τ_0_0>, @thick C<τ_0_0>.Type) -> () // CHECK-SAME: ) _ = #keyPath2(C, .nonfinal) // CHECK: keypath $KeyPath, S>, <τ_0_0 where τ_0_0 : P> ( // CHECK-SAME: root $C<τ_0_0>; // CHECK-SAME: gettable_property $S<τ_0_0>, // CHECK-SAME: id #C.computed!getter.1 : (C) -> () -> S, // CHECK-SAME: getter @_T08keypaths1CC8computedAA1SVyxGvTK : $@convention(thin) <τ_0_0> (@in C<τ_0_0>, @thick C<τ_0_0>.Type) -> @out S<τ_0_0> // CHECK-SAME: ) _ = #keyPath2(C, .computed) // CHECK: keypath $ReferenceWritableKeyPath, S>, <τ_0_0 where τ_0_0 : P> ( // CHECK-SAME: root $C<τ_0_0>; // CHECK-SAME: settable_property $S<τ_0_0>, // CHECK-SAME: id #C.observed!getter.1 : (C) -> () -> S, // CHECK-SAME: getter @_T08keypaths1CC8observedAA1SVyxGvTK : $@convention(thin) <τ_0_0> (@in C<τ_0_0>, @thick C<τ_0_0>.Type) -> @out S<τ_0_0>, // CHECK-SAME: setter @_T08keypaths1CC8observedAA1SVyxGvTk : $@convention(thin) <τ_0_0> (@in S<τ_0_0>, @in C<τ_0_0>, @thick C<τ_0_0>.Type) -> () // CHECK-SAME: ) _ = #keyPath2(C, .observed) _ = #keyPath2(C, .nonfinal.x) _ = #keyPath2(C, .computed.x) _ = #keyPath2(C, .observed.x) _ = #keyPath2(C, .z.computed) _ = #keyPath2(C, .z.observed) _ = #keyPath2(C, .observed.x) // CHECK: keypath $ReferenceWritableKeyPath, () -> ()>, <τ_0_0 where τ_0_0 : P> ( // CHECK-SAME: root $C<τ_0_0>; // CHECK-SAME: settable_property $() -> (), // CHECK-SAME: id ##C.reabstracted, // CHECK-SAME: getter @_T08keypaths1CC12reabstractedyycvTK : $@convention(thin) <τ_0_0> (@in C<τ_0_0>, @thick C<τ_0_0>.Type) -> @out @callee_owned (@in ()) -> @out (), // CHECK-SAME: setter @_T08keypaths1CC12reabstractedyycvTk : $@convention(thin) <τ_0_0> (@in @callee_owned (@in ()) -> @out (), @in C<τ_0_0>, @thick C<τ_0_0>.Type) -> () // CHECK-SAME: ) _ = #keyPath2(C, .reabstracted) // CHECK: keypath $KeyPath, C>, <τ_0_0 where τ_0_0 : P> ( // CHECK-SAME: root $S<τ_0_0>; gettable_property $C<τ_0_0>, // CHECK-SAME: id @_T08keypaths1SV8computedAA1CCyxGfg : $@convention(method) <τ_0_0> (@in_guaranteed S<τ_0_0>) -> @owned C<τ_0_0>, // CHECK-SAME: getter @_T08keypaths1SV8computedAA1CCyxGvTK : $@convention(thin) <τ_0_0> (@in S<τ_0_0>, @thick S<τ_0_0>.Type) -> @out C<τ_0_0> // CHECK-SAME: ) _ = #keyPath2(S, .computed) // CHECK: keypath $WritableKeyPath, C>, <τ_0_0 where τ_0_0 : P> ( // CHECK-SAME: root $S<τ_0_0>; // CHECK-SAME: settable_property $C<τ_0_0>, // CHECK-SAME: id @_T08keypaths1SV8observedAA1CCyxGfg : $@convention(method) <τ_0_0> (@in_guaranteed S<τ_0_0>) -> @owned C<τ_0_0>, // CHECK-SAME: getter @_T08keypaths1SV8observedAA1CCyxGvTK : $@convention(thin) <τ_0_0> (@in S<τ_0_0>, @thick S<τ_0_0>.Type) -> @out C<τ_0_0>, // CHECK-SAME: setter @_T08keypaths1SV8observedAA1CCyxGvTk : $@convention(thin) <τ_0_0> (@in C<τ_0_0>, @inout S<τ_0_0>, @thick S<τ_0_0>.Type) -> () // CHECK-SAME: ) _ = #keyPath2(S, .observed) _ = #keyPath2(S, .z.nonfinal) _ = #keyPath2(S, .z.computed) _ = #keyPath2(S, .z.observed) _ = #keyPath2(S, .computed.x) _ = #keyPath2(S, .computed.y) // CHECK: keypath $WritableKeyPath, () -> ()>, <τ_0_0 where τ_0_0 : P> ( // CHECK-SAME: root $S<τ_0_0>; // CHECK-SAME: settable_property $() -> (), // CHECK-SAME: id ##S.reabstracted, // CHECK-SAME: getter @_T08keypaths1SV12reabstractedyycvTK : $@convention(thin) <τ_0_0> (@in S<τ_0_0>, @thick S<τ_0_0>.Type) -> @out @callee_owned (@in ()) -> @out (), // CHECK-SAME: setter @_T08keypaths1SV12reabstractedyycvTk : $@convention(thin) <τ_0_0> (@in @callee_owned (@in ()) -> @out (), @inout S<τ_0_0>, @thick S<τ_0_0>.Type) -> () // CHECK-SAME: ) _ = #keyPath2(S, .reabstracted) // CHECK: keypath $KeyPath, <τ_0_0 where τ_0_0 : P> ( // CHECK-SAME: root $τ_0_0; // CHECK-SAME: gettable_property $Int, // CHECK-SAME: id #P.x!getter.1 : (Self) -> () -> Int, // CHECK-SAME: getter @_T08keypaths1PP1xSivTK : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in τ_0_0) -> @out Int // CHECK-SAME: ) _ = #keyPath2(T, .x) // CHECK: keypath $WritableKeyPath, <τ_0_0 where τ_0_0 : P> ( // CHECK-SAME: root $τ_0_0; // CHECK-SAME: settable_property $String, // CHECK-SAME: id #P.y!getter.1 : (Self) -> () -> String, // CHECK-SAME: getter @_T08keypaths1PP1ySSvTK : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in τ_0_0) -> @out String, // CHECK-SAME: setter @_T08keypaths1PP1ySSvTk : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in String, @inout τ_0_0) -> () // CHECK-SAME: ) _ = #keyPath2(T, .y) }