// RUN: %target-swift-emit-silgen -enable-experimental-feature KeyPathWithMethodMembers -Xllvm -sil-print-types -target %target-swift-5.1-abi-triple -parse-stdlib -module-name keypaths %s | %FileCheck %s // REQUIRES: swift_feature_KeyPathWithMethodMembers import Swift 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() } } extension C { var `extension`: S { fatalError() } } protocol P { var x: Int { get } var y: String { get set } } extension P { var z: String { return y } var w: String { get { return "" } nonmutating set { } } } struct T { var a: (Int, String) let b: (f: String, g: Int) let c: (x: C, y: C) } /* TODO: When we support superclass requirements on protocols, we should test * this case as well. protocol PoC : C {} */ // CHECK-LABEL: sil hidden [ossa] @{{.*}}storedProperties func storedProperties(_: T) { // CHECK: keypath $WritableKeyPath, T>, <τ_0_0> (root $S<τ_0_0>; stored_property #S.x : $τ_0_0) _ = \S.x // CHECK: keypath $KeyPath, String>, <τ_0_0> (root $S<τ_0_0>; stored_property #S.y : $String) _ = \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) _ = \S.z.x // CHECK: keypath $ReferenceWritableKeyPath, T>, <τ_0_0> (root $C<τ_0_0>; stored_property #C.x : $τ_0_0) _ = \C.x // CHECK: keypath $KeyPath, String>, <τ_0_0> (root $C<τ_0_0>; stored_property #C.y : $String) _ = \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) _ = \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) _ = \C.z.z.y } // CHECK-LABEL: sil hidden [ossa] @{{.*}}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 : (C) -> () -> S, // CHECK-SAME: getter @$s8keypaths1CC8nonfinalAA1SVyxGvpAA1PRzlACyxGTK : $@convention(keypath_accessor_getter) <τ_0_0 where τ_0_0 : P> (@in_guaranteed C<τ_0_0>) -> @out S<τ_0_0>, // CHECK-SAME: setter @$s8keypaths1CC8nonfinalAA1SVyxGvpAA1PRzlACyxGTk : $@convention(keypath_accessor_setter) <τ_0_0 where τ_0_0 : P> (@in_guaranteed S<τ_0_0>, @in_guaranteed C<τ_0_0>) -> () // CHECK-SAME: ) _ = \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 : (C) -> () -> S, // CHECK-SAME: getter @$s8keypaths1CC8computedAA1SVyxGvpAA1PRzlACyxGTK : $@convention(keypath_accessor_getter) <τ_0_0 where τ_0_0 : P> (@in_guaranteed C<τ_0_0>) -> @out S<τ_0_0> // CHECK-SAME: ) _ = \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 : (C) -> () -> S, // CHECK-SAME: getter @$s8keypaths1CC8observedAA1SVyxGvpAA1PRzlACyxGTK : $@convention(keypath_accessor_getter) <τ_0_0 where τ_0_0 : P> (@in_guaranteed C<τ_0_0>) -> @out S<τ_0_0>, // CHECK-SAME: setter @$s8keypaths1CC8observedAA1SVyxGvpAA1PRzlACyxGTk : $@convention(keypath_accessor_setter) <τ_0_0 where τ_0_0 : P> (@in_guaranteed S<τ_0_0>, @in_guaranteed C<τ_0_0>) -> () // CHECK-SAME: ) _ = \C.observed _ = \C.nonfinal.x _ = \C.computed.x _ = \C.observed.x _ = \C.z.computed _ = \C.z.observed _ = \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 @$s8keypaths1CC12reabstractedyycvpAA1PRzlACyxGTK : $@convention(keypath_accessor_getter) <τ_0_0 where τ_0_0 : P> (@in_guaranteed C<τ_0_0>) -> @out @callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for <()>, // CHECK-SAME: setter @$s8keypaths1CC12reabstractedyycvpAA1PRzlACyxGTk : $@convention(keypath_accessor_setter) <τ_0_0 where τ_0_0 : P> (@in_guaranteed @callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for <()>, @in_guaranteed C<τ_0_0>) -> () // CHECK-SAME: ) _ = \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 @$s8keypaths1SV8computedAA1CCyxGvg : $@convention(method) <τ_0_0> (@in_guaranteed S<τ_0_0>) -> @owned C<τ_0_0>, // CHECK-SAME: getter @$s8keypaths1SV8computedAA1CCyxGvpAA1PRzlACyxGTK : $@convention(keypath_accessor_getter) <τ_0_0 where τ_0_0 : P> (@in_guaranteed S<τ_0_0>) -> @out C<τ_0_0> // CHECK-SAME: ) _ = \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 @$s8keypaths1SV8observedAA1CCyxGvg : $@convention(method) <τ_0_0> (@in_guaranteed S<τ_0_0>) -> @owned C<τ_0_0>, // CHECK-SAME: getter @$s8keypaths1SV8observedAA1CCyxGvpAA1PRzlACyxGTK : $@convention(keypath_accessor_getter) <τ_0_0 where τ_0_0 : P> (@in_guaranteed S<τ_0_0>) -> @out C<τ_0_0>, // CHECK-SAME: setter @$s8keypaths1SV8observedAA1CCyxGvpAA1PRzlACyxGTk : $@convention(keypath_accessor_setter) <τ_0_0 where τ_0_0 : P> (@in_guaranteed C<τ_0_0>, @inout S<τ_0_0>) -> () // CHECK-SAME: ) _ = \S.observed _ = \S.z.nonfinal _ = \S.z.computed _ = \S.z.observed _ = \S.computed.x _ = \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 @$s8keypaths1SV12reabstractedyycvpAA1PRzlACyxGTK : $@convention(keypath_accessor_getter) <τ_0_0 where τ_0_0 : P> (@in_guaranteed S<τ_0_0>) -> @out @callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for <()>, // CHECK-SAME: setter @$s8keypaths1SV12reabstractedyycvpAA1PRzlACyxGTk : $@convention(keypath_accessor_setter) <τ_0_0 where τ_0_0 : P> (@in_guaranteed @callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for <()>, @inout S<τ_0_0>) -> () // CHECK-SAME: ) _ = \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 : (Self) -> () -> Int, // CHECK-SAME: getter @$s8keypaths1PP1xSivpAaBRzlxTK : $@convention(keypath_accessor_getter) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out Int // CHECK-SAME: ) _ = \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 : (Self) -> () -> String, // CHECK-SAME: getter @$s8keypaths1PP1ySSvpAaBRzlxTK : $@convention(keypath_accessor_getter) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out String, // CHECK-SAME: setter @$s8keypaths1PP1ySSvpAaBRzlxTk : $@convention(keypath_accessor_setter) <τ_0_0 where τ_0_0 : P> (@in_guaranteed String, @inout τ_0_0) -> () // CHECK-SAME: ) _ = \T.y // CHECK: keypath $KeyPath, <τ_0_0 where τ_0_0 : P> ( // CHECK-SAME: root $τ_0_0; // CHECK-SAME: gettable_property $String, // CHECK-SAME: id @$s8keypaths1PPAAE1zSSvg _ = \T.z } struct Concrete: P { var x: Int var y: String } // CHECK-LABEL: sil hidden [ossa] @$s8keypaths35keyPathsWithSpecificGenericInstanceyyF func keyPathsWithSpecificGenericInstance() { // CHECK: keypath $KeyPath, ( // CHECK-SAME: gettable_property $String, // CHECK-SAME: id @$s8keypaths1PPAAE1zSSvg // CHECK-SAME: getter @$s8keypaths1PPAAE1zSSvpAA8ConcreteVTK : $@convention(keypath_accessor_getter) (@in_guaranteed Concrete) -> @out String _ = \Concrete.z _ = \S.computed } class AA { var a: Int { get { return 0 } set { } } } class BB: AA { } func keyPathForInheritedMember() { _ = \BB.a } func keyPathForExistentialMember() { _ = \P.x _ = \P.y _ = \P.z _ = \P.w } struct OptionalFields { var x: S? } struct OptionalFields2 { var y: OptionalFields? } // CHECK-LABEL: sil hidden [ossa] @$s8keypaths18keyPathForOptionalyyF func keyPathForOptional() { // CHECK: keypath $WritableKeyPath>, ( // CHECK-SAME: stored_property #OptionalFields.x : $Optional>; // CHECK-SAME: optional_force : $S) _ = \OptionalFields.x! // CHECK: keypath $KeyPath>, ( // CHECK-SAME: stored_property #OptionalFields.x : $Optional>; // CHECK-SAME: optional_chain : $S; // CHECK-SAME: stored_property #S.y : $String; // CHECK-SAME: optional_wrap : $Optional) _ = \OptionalFields.x?.y // CHECK: keypath $KeyPath>>, ( // CHECK-SAME: root $OptionalFields2; // CHECK-SAME: stored_property #OptionalFields2.y : $Optional; // CHECK-SAME: optional_chain : $OptionalFields; // CHECK-SAME: stored_property #OptionalFields.x : $Optional>) _ = \OptionalFields2.y?.x } class StorageQualified { weak var tooWeak: StorageQualified? unowned var disowned: StorageQualified init() { fatalError() } } final class FinalStorageQualified { weak var tooWeak: StorageQualified? unowned var disowned: StorageQualified init() { fatalError() } } // CHECK-LABEL: sil hidden [ossa] @{{.*}}keyPathForStorageQualified func keyPathForStorageQualified() { // CHECK: = keypath $ReferenceWritableKeyPath>, // CHECK-SAME: settable_property $Optional, id #StorageQualified.tooWeak!getter _ = \StorageQualified.tooWeak // CHECK: = keypath $ReferenceWritableKeyPath, // CHECK-SAME: settable_property $StorageQualified, id #StorageQualified.disowned!getter _ = \StorageQualified.disowned // CHECK: = keypath $ReferenceWritableKeyPath>, // CHECK-SAME: settable_property $Optional, id ##FinalStorageQualified.tooWeak _ = \FinalStorageQualified.tooWeak // CHECK: = keypath $ReferenceWritableKeyPath, // CHECK-SAME: settable_property $StorageQualified, id ##FinalStorageQualified.disowned _ = \FinalStorageQualified.disowned } struct IUOProperty { var iuo: IUOBlob! } struct IUOBlob { var x: Int subscript(y: String) -> String { get { return y } set {} } } // CHECK-LABEL: sil hidden [ossa] @{{.*}}11iuoKeyPaths func iuoKeyPaths() { // CHECK: = keypath $WritableKeyPath, // CHECK-SAME: stored_property #IUOProperty.iuo // CHECK-SAME: optional_force // CHECK-SAME: stored_property #IUOBlob.x _ = \IUOProperty.iuo.x // CHECK: = keypath $WritableKeyPath, // CHECK-SAME: stored_property #IUOProperty.iuo // CHECK-SAME: optional_force // CHECK-SAME: stored_property #IUOBlob.x _ = \IUOProperty.iuo!.x } class Bass: Hashable { static func ==(_: Bass, _: Bass) -> Bool { return false } func hash(into hasher: inout Hasher) {} } class Treble: Bass { } struct Subscripts { subscript() -> T { get { fatalError() } set { fatalError() } } subscript(generic x: T) -> T { get { fatalError() } set { fatalError() } } subscript(concrete x: String) -> String { get { fatalError() } set { fatalError() } } subscript(x: String, y: String) -> String { get { fatalError() } set { fatalError() } } subscript(subGeneric z: U) -> U { get { fatalError() } set { fatalError() } } subscript(mutable x: T) -> T { get { fatalError() } set { fatalError() } } subscript(bass: Bass) -> Bass { get { return bass } set { } } } struct SubscriptDefaults1 { subscript(x: Int = 0) -> Int { get { fatalError() } set { fatalError() } } subscript(x: Int, y: Int, z: Int = 0) -> Int { get { fatalError() } set { fatalError() } } subscript(x: Bool, bool y: Bool = false) -> Bool { get { fatalError() } set { fatalError() } } subscript(bool x: Bool, y: Int, z: Int = 0) -> Int { get { fatalError() } set { fatalError() } } } struct SubscriptDefaults2 { subscript(x: Int? = nil) -> Int { get { fatalError() } set { fatalError() } } } struct SubscriptDefaults3 { subscript(x: Int = #line) -> Int { get { fatalError() } set { fatalError() } } } struct SubscriptDefaults4 { subscript(x x: T, y y: T = 0) -> T { get { fatalError() } set { fatalError() } } } struct SubscriptDefaults5 { subscript(x x: T, y y: T = #function) -> T { get { fatalError() } set { fatalError() } } } // CHECK-LABEL: sil hidden [ossa] @{{.*}}10subscripts1x1y1syx_q_SStSHRzSHR_r0_lF func subscripts(x: T, y: U, s: String) { _ = \Subscripts.[] _ = \Subscripts.[generic: x] _ = \Subscripts.[concrete: s] _ = \Subscripts.[s, s] _ = \Subscripts.[subGeneric: s] _ = \Subscripts.[subGeneric: x] _ = \Subscripts.[subGeneric: y] _ = \Subscripts.[] _ = \Subscripts.[generic: y] _ = \Subscripts.[concrete: s] _ = \Subscripts.[s, s] _ = \Subscripts.[subGeneric: s] _ = \Subscripts.[subGeneric: x] _ = \Subscripts.[subGeneric: y] _ = \Subscripts.[] _ = \Subscripts.[generic: s] _ = \Subscripts.[concrete: s] _ = \Subscripts.[s, s] _ = \Subscripts.[subGeneric: s] _ = \Subscripts.[subGeneric: x] _ = \Subscripts.[subGeneric: y] _ = \Subscripts.[s, s].count _ = \Subscripts.[Bass()] _ = \Subscripts.[Treble()] _ = \SubscriptDefaults1.[] _ = \SubscriptDefaults1.[0] _ = \SubscriptDefaults1.[0, 0] _ = \SubscriptDefaults1.[0, 0, 0] _ = \SubscriptDefaults1.[false] _ = \SubscriptDefaults1.[false, bool: false] _ = \SubscriptDefaults1.[bool: false, 0] _ = \SubscriptDefaults1.[bool: false, 0, 0] _ = \SubscriptDefaults2.[] _ = \SubscriptDefaults2.[0] _ = \SubscriptDefaults3.[] _ = \SubscriptDefaults3.[0] _ = \SubscriptDefaults4.[x: 0] _ = \SubscriptDefaults4.[x: 0, y: 0] _ = \SubscriptDefaults5.[x: ""] _ = \SubscriptDefaults5.[x: "", y: ""] } // CHECK-LABEL: sil hidden [ossa] @{{.*}}check_default_subscripts func check_default_subscripts() { // CHECK: [[INTX:%[0-9]+]] = integer_literal $Builtin.IntLiteral, 0 // CHECK: [[IX:%[0-9]+]] = apply %{{[0-9]+}}([[INTX]], {{.*}} // CHECK: [[INTY:%[0-9]+]] = integer_literal $Builtin.IntLiteral, 0 // CHECK: [[IY:%[0-9]+]] = apply %{{[0-9]+}}([[INTY]], {{.*}} // CHECK: [[KEYPATH:%[0-9]+]] = keypath $WritableKeyPath, (root $SubscriptDefaults4; settable_property $Int, id @$s8keypaths18SubscriptDefaults4V1x1yxx_xtcSjRzluig : $@convention(method) <τ_0_0 where τ_0_0 : Numeric> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, SubscriptDefaults4) -> @out τ_0_0, getter @$s8keypaths18SubscriptDefaults4V1x1yxx_xtcSjRzluipACSiTK : $@convention(keypath_accessor_getter) (@in_guaranteed SubscriptDefaults4, @in_guaranteed (Int, Int)) -> @out Int, setter @$s8keypaths18SubscriptDefaults4V1x1yxx_xtcSjRzluipACSiTk : $@convention(keypath_accessor_setter) (@in_guaranteed Int, @inout SubscriptDefaults4, @in_guaranteed (Int, Int)) -> (), indices [%$0 : $Int : $Int, %$1 : $Int : $Int], indices_equals @$sS2iTH : $@convention(keypath_accessor_equals) (@in_guaranteed (Int, Int), @in_guaranteed (Int, Int)) -> Bool, indices_hash @$sS2iTh : $@convention(keypath_accessor_hash) (@in_guaranteed (Int, Int)) -> Int) ([[IX]], [[IY]]) _ = \SubscriptDefaults4.[x: 0, y: 0] // CHECK: [[INTINIT:%[0-9]+]] = integer_literal $Builtin.IntLiteral, 0 // CHECK: [[I:%[0-9]+]] = apply %{{[0-9]+}}([[INTINIT]], {{.*}} // CHECK: [[DFN:%[0-9]+]] = function_ref @$s8keypaths18SubscriptDefaults4V1x1yxx_xtcSjRzluipfA0_ : $@convention(thin) <τ_0_0 where τ_0_0 : Numeric> () -> @out τ_0_0 // CHECK: [[ALLOC:%[0-9]+]] = alloc_stack $Int // CHECK: apply [[DFN]]([[ALLOC]]) : $@convention(thin) <τ_0_0 where τ_0_0 : Numeric> () -> @out τ_0_0 // CHECK: [[LOAD:%[0-9]+]] = load [trivial] [[ALLOC]] : $*Int // CHECK: [[KEYPATH:%[0-9]+]] = keypath $WritableKeyPath, (root $SubscriptDefaults4; settable_property $Int, id @$s8keypaths18SubscriptDefaults4V1x1yxx_xtcSjRzluig : $@convention(method) <τ_0_0 where τ_0_0 : Numeric> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, SubscriptDefaults4) -> @out τ_0_0, getter @$s8keypaths18SubscriptDefaults4V1x1yxx_xtcSjRzluipACSiTK : $@convention(keypath_accessor_getter) (@in_guaranteed SubscriptDefaults4, @in_guaranteed (Int, Int)) -> @out Int, setter @$s8keypaths18SubscriptDefaults4V1x1yxx_xtcSjRzluipACSiTk : $@convention(keypath_accessor_setter) (@in_guaranteed Int, @inout SubscriptDefaults4, @in_guaranteed (Int, Int)) -> (), indices [%$0 : $Int : $Int, %$1 : $Int : $Int], indices_equals @$sS2iTH : $@convention(keypath_accessor_equals) (@in_guaranteed (Int, Int), @in_guaranteed (Int, Int)) -> Bool, indices_hash @$sS2iTh : $@convention(keypath_accessor_hash) (@in_guaranteed (Int, Int)) -> Int) ([[I]], [[LOAD]]) _ = \SubscriptDefaults4.[x: 0] // CHECK: [[STRX_LIT:%[0-9]+]] = string_literal utf8 "" // CHECK: [[STRX:%[0-9]+]] = apply %{{[0-9]+}}([[STRX_LIT]], {{.*}} // CHECK: [[STRY_LIT:%[0-9]+]] = string_literal utf8 "check_default_subscripts()" // CHECK: [[DEF_ARG:%[0-9]+]] = apply %{{[0-9]+}}([[STRY_LIT]], {{.*}} // CHECK: keypath $WritableKeyPath, (root $SubscriptDefaults5; settable_property $String, id @$s8keypaths18SubscriptDefaults5V1x1yxx_xtcs26ExpressibleByStringLiteralRzluig : $@convention(method) <τ_0_0 where τ_0_0 : ExpressibleByStringLiteral> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, SubscriptDefaults5) -> @out τ_0_0, getter @$s8keypaths18SubscriptDefaults5V1x1yxx_xtcs26ExpressibleByStringLiteralRzluipACSSTK : $@convention(keypath_accessor_getter) (@in_guaranteed SubscriptDefaults5, @in_guaranteed (String, String)) -> @out String, setter @$s8keypaths18SubscriptDefaults5V1x1yxx_xtcs26ExpressibleByStringLiteralRzluipACSSTk : $@convention(keypath_accessor_setter) (@in_guaranteed String, @inout SubscriptDefaults5, @in_guaranteed (String, String)) -> (), indices [%$0 : $String : $String, %$1 : $String : $String], indices_equals @$sS2STH : $@convention(keypath_accessor_equals) (@in_guaranteed (String, String), @in_guaranteed (String, String)) -> Bool, indices_hash @$sS2STh : $@convention(keypath_accessor_hash) (@in_guaranteed (String, String)) -> Int) ([[STRX]], [[DEF_ARG]]) _ = \SubscriptDefaults5.[x: ""] // CHECK: [[STRX_LIT:%[0-9]+]] = string_literal utf8 "" // CHECK: [[STRX:%[0-9]+]] = apply %{{[0-9]+}}([[STRX_LIT]], {{.*}} // CHECK: [[STRY_LIT:%[0-9]+]] = string_literal utf8 "" // CHECK: [[STRY:%[0-9]+]] = apply %{{[0-9]+}}([[STRY_LIT]], {{.*}} // CHECK: keypath $WritableKeyPath, (root $SubscriptDefaults5; settable_property $String, id @$s8keypaths18SubscriptDefaults5V1x1yxx_xtcs26ExpressibleByStringLiteralRzluig : $@convention(method) <τ_0_0 where τ_0_0 : ExpressibleByStringLiteral> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0, SubscriptDefaults5) -> @out τ_0_0, getter @$s8keypaths18SubscriptDefaults5V1x1yxx_xtcs26ExpressibleByStringLiteralRzluipACSSTK : $@convention(keypath_accessor_getter) (@in_guaranteed SubscriptDefaults5, @in_guaranteed (String, String)) -> @out String, setter @$s8keypaths18SubscriptDefaults5V1x1yxx_xtcs26ExpressibleByStringLiteralRzluipACSSTk : $@convention(keypath_accessor_setter) (@in_guaranteed String, @inout SubscriptDefaults5, @in_guaranteed (String, String)) -> (), indices [%$0 : $String : $String, %$1 : $String : $String], indices_equals @$sS2STH : $@convention(keypath_accessor_equals) (@in_guaranteed (String, String), @in_guaranteed (String, String)) -> Bool, indices_hash @$sS2STh : $@convention(keypath_accessor_hash) (@in_guaranteed (String, String)) -> Int) ([[STRX]], [[STRY]]) _ = \SubscriptDefaults5.[x: "", y: ""] } struct SubscriptVariadic1 { subscript(x: Int...) -> Int { x[0] } } struct SubscriptVariadic2 { subscript(x: T...) -> T { x[0] } } struct SubscriptVariadic3 { subscript(x: T...) -> T { x[0] } } // CHECK-LABEL: sil hidden [ossa] @{{.*}}test_variadics func test_variadics() { // CHECK: [[ARR_COUNT:%[0-9]+]] = integer_literal $Builtin.Word, 3 // CHECK: [[FN_REF:%[0-9]+]] = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF // CHECK: [[MAKE_ARR:%[0-9]+]] = apply [[FN_REF]]([[ARR_COUNT]]) // CHECK: ([[ARR:%[0-9]+]], %{{[0-9]+}}) = destructure_tuple [[MAKE_ARR]] : $(Array, Builtin.RawPointer) // CHECK: [[FIN_REF:%[0-9]+]] = function_ref @$ss27_finalizeUninitializedArrayySayxGABnlF // CHECK: [[FIN_ARR:%[0-9]+]] = apply [[FIN_REF]]([[ARR]]) // CHECK: keypath $KeyPath, (root $SubscriptVariadic1; gettable_property $Int, id @$s8keypaths18SubscriptVariadic1VyS2id_tcig : $@convention(method) (@guaranteed Array, SubscriptVariadic1) -> Int, getter @$s8keypaths18SubscriptVariadic1VyS2id_tcipACTK : $@convention(keypath_accessor_getter) (@in_guaranteed SubscriptVariadic1, @in_guaranteed Array) -> @out Int, indices [%$0 : $Array : $Array], indices_equals @$sSaySiGTH : $@convention(keypath_accessor_equals) (@in_guaranteed Array, @in_guaranteed Array) -> Bool, indices_hash @$sSaySiGTh : $@convention(keypath_accessor_hash) (@in_guaranteed Array) -> Int) ([[FIN_ARR]]) _ = \SubscriptVariadic1.[1, 2, 3] // CHECK: [[ARR_COUNT:%[0-9]+]] = integer_literal $Builtin.Word, 1 // CHECK: [[FN_REF:%[0-9]+]] = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF // CHECK: [[MAKE_ARR:%[0-9]+]] = apply [[FN_REF]]([[ARR_COUNT]]) // CHECK: ([[ARR:%[0-9]+]], %{{[0-9]+}}) = destructure_tuple [[MAKE_ARR]] : $(Array, Builtin.RawPointer) // CHECK: [[FIN_REF:%[0-9]+]] = function_ref @$ss27_finalizeUninitializedArrayySayxGABnlF // CHECK: [[FIN_ARR:%[0-9]+]] = apply [[FIN_REF]]([[ARR]]) // CHECK: keypath $KeyPath, (root $SubscriptVariadic1; gettable_property $Int, id @$s8keypaths18SubscriptVariadic1VyS2id_tcig : $@convention(method) (@guaranteed Array, SubscriptVariadic1) -> Int, getter @$s8keypaths18SubscriptVariadic1VyS2id_tcipACTK : $@convention(keypath_accessor_getter) (@in_guaranteed SubscriptVariadic1, @in_guaranteed Array) -> @out Int, indices [%$0 : $Array : $Array], indices_equals @$sSaySiGTH : $@convention(keypath_accessor_equals) (@in_guaranteed Array, @in_guaranteed Array) -> Bool, indices_hash @$sSaySiGTh : $@convention(keypath_accessor_hash) (@in_guaranteed Array) -> Int) ([[FIN_ARR]]) _ = \SubscriptVariadic1.[1] // CHECK: [[ARR_COUNT:%[0-9]+]] = integer_literal $Builtin.Word, 0 // CHECK: [[FN_REF:%[0-9]+]] = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF // CHECK: [[MAKE_ARR:%[0-9]+]] = apply [[FN_REF]]([[ARR_COUNT]]) // CHECK: ([[ARR:%[0-9]+]], %{{[0-9]+}}) = destructure_tuple [[MAKE_ARR]] : $(Array, Builtin.RawPointer) // CHECK: keypath $KeyPath, (root $SubscriptVariadic1; gettable_property $Int, id @$s8keypaths18SubscriptVariadic1VyS2id_tcig : $@convention(method) (@guaranteed Array, SubscriptVariadic1) -> Int, getter @$s8keypaths18SubscriptVariadic1VyS2id_tcipACTK : $@convention(keypath_accessor_getter) (@in_guaranteed SubscriptVariadic1, @in_guaranteed Array) -> @out Int, indices [%$0 : $Array : $Array], indices_equals @$sSaySiGTH : $@convention(keypath_accessor_equals) (@in_guaranteed Array, @in_guaranteed Array) -> Bool, indices_hash @$sSaySiGTh : $@convention(keypath_accessor_hash) (@in_guaranteed Array) -> Int) ([[ARR]]) _ = \SubscriptVariadic1.[] _ = \SubscriptVariadic2.["", "1"] _ = \SubscriptVariadic2.[""] // CHECK: [[ARR_COUNT:%[0-9]+]] = integer_literal $Builtin.Word, 2 // CHECK: [[FN_REF:%[0-9]+]] = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF // CHECK: [[MAKE_ARR:%[0-9]+]] = apply [[FN_REF]]([[ARR_COUNT]]) // CHECK: ([[ARR:%[0-9]+]], %{{[0-9]+}}) = destructure_tuple [[MAKE_ARR]] : $(Array, Builtin.RawPointer) // CHECK: [[FIN_REF:%[0-9]+]] = function_ref @$ss27_finalizeUninitializedArrayySayxGABnlF // CHECK: [[FIN_ARR:%[0-9]+]] = apply [[FIN_REF]]([[ARR]]) // CHECK: keypath $KeyPath, (root $SubscriptVariadic2; gettable_property $String, id @$s8keypaths18SubscriptVariadic2Vyxxd_tcs26ExpressibleByStringLiteralRzluig : $@convention(method) <τ_0_0 where τ_0_0 : ExpressibleByStringLiteral> (@guaranteed Array<τ_0_0>, SubscriptVariadic2) -> @out τ_0_0, getter @$s8keypaths18SubscriptVariadic2Vyxxd_tcs26ExpressibleByStringLiteralRzluipACSSTK : $@convention(keypath_accessor_getter) (@in_guaranteed SubscriptVariadic2, @in_guaranteed Array) -> @out String, indices [%$0 : $Array : $Array], indices_equals @$sSaySSGTH : $@convention(keypath_accessor_equals) (@in_guaranteed Array, @in_guaranteed Array) -> Bool, indices_hash @$sSaySSGTh : $@convention(keypath_accessor_hash) (@in_guaranteed Array) -> Int) ([[FIN_ARR]]) _ = \SubscriptVariadic2.["", #function] _ = \SubscriptVariadic3.[""] _ = \SubscriptVariadic3.["", "1"] _ = \SubscriptVariadic3.[] } // CHECK-LABEL: sil hidden [ossa] @{{.*}}subclass_generics func subclass_generics, U: C, V/*: PoC*/>(_: T, _: U, _: V) { _ = \T.x _ = \T.z _ = \T.computed _ = \T.extension _ = \U.x _ = \U.z _ = \U.computed _ = \U.extension /* _ = \V.x _ = \V.z _ = \V.computed _ = \V.extension */ _ = \(C & P).x _ = \(C & P).z _ = \(C & P).computed _ = \(C & P).extension _ = \(C & P).x _ = \(C & P).z _ = \(C & P).computed _ = \(C & P).extension /* TODO: When we support superclass requirements on protocols, we should test * this case as well. _ = \PoC.x _ = \PoC.z _ = \PoC.computed _ = \PoC.extension */ } // CHECK-LABEL: sil hidden [ossa] @{{.*}}identity func identity(_: T) { // CHECK: keypath $WritableKeyPath, <τ_0_0> ({{.*}}root $τ_0_0) let _: WritableKeyPath = \T.self // CHECK: keypath $WritableKeyPath, Array>, <τ_0_0> ({{.*}}root $Array<τ_0_0>) let _: WritableKeyPath<[T], [T]> = \[T].self // CHECK: keypath $WritableKeyPath, ({{.*}}root $String) let _: WritableKeyPath = \String.self } // CHECK-LABEL: sil hidden [ossa] @{{.*}}tuples func tuples(_: T) { // CHECK: keypath $WritableKeyPath, (root $T; stored_property #T.a : $(Int, String); tuple_element #0 : $Int) let _: WritableKeyPath = \T.a.0 // CHECK: keypath $WritableKeyPath, (root $T; stored_property #T.a : $(Int, String); tuple_element #1 : $String) let _: WritableKeyPath = \T.a.1 // CHECK: keypath $KeyPath, (root $T; stored_property #T.b : $(f: String, g: Int); tuple_element #0 : $String) let _: KeyPath = \T.b.f // CHECK: keypath $KeyPath, (root $T; stored_property #T.b : $(f: String, g: Int); tuple_element #1 : $Int) let _: KeyPath = \T.b.g // CHECK: keypath $KeyPath>, (root $T; stored_property #T.c : $(x: C, y: C); tuple_element #0 : $C) let _: KeyPath> = \T.c.x // CHECK: keypath $KeyPath>, (root $T; stored_property #T.c : $(x: C, y: C); tuple_element #1 : $C) let _: KeyPath> = \T.c.y // CHECK: keypath $ReferenceWritableKeyPath, (root $T; stored_property #T.c : $(x: C, y: C); tuple_element #0 : $C; stored_property #C.x : $Int) let _: ReferenceWritableKeyPath = \T.c.x.x // CHECK: keypath $KeyPath, (root $T; stored_property #T.c : $(x: C, y: C); tuple_element #0 : $C; stored_property #C.y : $String) let _: KeyPath = \T.c.x.y typealias Thing = (type: Any.Type, fn: () -> ()) // CHECK: keypath $WritableKeyPath<(type: any Any.Type, fn: () -> ()), any Any.Type>, (root $(type: any Any.Type, fn: () -> ()); tuple_element #0 : $any Any.Type) let _: WritableKeyPath = \Thing.type // CHECK: keypath $WritableKeyPath<(type: any Any.Type, fn: () -> ()), () -> ()>, (root $(type: any Any.Type, fn: () -> ()); tuple_element #1 : $() -> ()) let _: WritableKeyPath ()> = \Thing.fn } // CHECK-LABEL: sil hidden [ossa] @{{.*}}tuples_generic func tuples_generic(_: T, _: U, _: V) { typealias TUC = (T, U, C) // CHECK: keypath $WritableKeyPath<(T, U, C), T>, <τ_0_0, τ_0_1, τ_0_2> (root $(τ_0_0, τ_0_1, C<τ_0_2>); tuple_element #0 : $τ_0_0) let _: WritableKeyPath = \TUC.0 // CHECK: keypath $WritableKeyPath<(T, U, C), U>, <τ_0_0, τ_0_1, τ_0_2> (root $(τ_0_0, τ_0_1, C<τ_0_2>); tuple_element #1 : $τ_0_1) let _: WritableKeyPath = \TUC.1 // CHECK: keypath $ReferenceWritableKeyPath<(T, U, C), V>, <τ_0_0, τ_0_1, τ_0_2> (root $(τ_0_0, τ_0_1, C<τ_0_2>); tuple_element #2 : $C<τ_0_2>; stored_property #C.x : $τ_0_2) let _: ReferenceWritableKeyPath = \TUC.2.x // CHECK: keypath $KeyPath<(T, U, C), String>, <τ_0_0, τ_0_1, τ_0_2> (root $(τ_0_0, τ_0_1, C<τ_0_2>); tuple_element #2 : $C<τ_0_2>; stored_property #C.y : $String) let _: KeyPath = \TUC.2.y } protocol DefineSomeType { associatedtype SomeType func defineSome() -> SomeType } protocol A {} extension Int : A {} struct TestKeyPathWithSomeType : DefineSomeType { func defineSome() -> some A { return 0 } func testKeyPathWithSome() { _ = \S.y _ = \S.z.x _ = \C.x _ = \C.y _ = \C.z.x _ = \C.z.z.y _ = \C.nonfinal _ = \C.computed _ = \C.observed _ = \C.nonfinal.x _ = \C.computed.x _ = \C.observed.x _ = \C.z.computed _ = \C.z.observed _ = \C.observed.x _ = \C.reabstracted _ = \S.computed _ = \S.observed _ = \S.z.nonfinal _ = \S.z.computed _ = \S.z.observed _ = \S.computed.x _ = \S.computed.y _ = \S.reabstracted } } class J: Hashable { static func == (lhs: J, rhs: J) -> Bool { return lhs === rhs } func hash(into hasher: inout Hasher) { hasher.combine(ObjectIdentifier(self)) } } struct K { var year = 2024 static let millenium: Int = 3 init() {} init(val value: Int = 2024) { year = value } var add: (Int, Int) -> Int { return { $0 + $1 } } func add(this: Int) -> Int { this + this} func add(that: Int) -> Int { that + that } static func subtract(_ val: Int) -> Int { return millenium - val } nonisolated func nonisolatedNextYear() -> Int { year + 1 } func doubleValue(_ value: inout Int) { value *= 2 } func foo(hashableParam j: J) {} subscript(index: Int) -> Int { return year + index} } protocol Describable { func describe() -> String } struct L: Describable { var name: String func describe() -> String { return "\(name)" } } // CHECK-LABEL: // test_method_and_initializer_keypaths() // CHECK-LABEL: sil hidden [ossa] @{{.*}} : $@convention(thin) () -> () { func test_method_and_initializer_keypaths() { // CHECK: %0 = keypath $WritableKeyPath K> // CHECK-SAME: root $K.Type; gettable_property $() -> K, id @$s8keypaths1KVACycfC : $@convention(method) (@thin K.Type) -> K, getter @$s8keypaths1KVACycfcACmTkmu : $@convention(keypath_accessor_getter) (@in_guaranteed @thick K.Type) -> @out @callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for ) let _ = \K.Type.init // CHECK: keypath $WritableKeyPath, (root $K.Type; gettable_property $K, id @$s8keypaths1KVACycfC : $@convention(method) (@thin K.Type) -> K, getter @$s8keypaths1KVACycfcACmTkMA : $@convention(keypath_accessor_getter) (@in_guaranteed @thick K.Type) -> @out K) let _ = \K.Type.init() // CHECK: keypath $WritableKeyPath K> // CHECK-SAME: root $K.Type; gettable_property $(Int) -> K, id @$s8keypaths1KV3valACSi_tcfC : $@convention(method) (Int, @thin K.Type) -> K, getter @$s8keypaths1KV3valACSi_tcfcACmTkmu : $@convention(keypath_accessor_getter) (@in_guaranteed @thick K.Type) -> @out @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1 for ) let _ = \K.Type.init(val:) // CHECK: keypath $WritableKeyPath, (root $K.Type; gettable_property $K, id @$s8keypaths1KV3valACSi_tcfC : $@convention(method) (Int, @thin K.Type) -> K, getter @$s8keypaths1KV3valACSi_tcfcACmTkMA : $@convention(keypath_accessor_getter) (@in_guaranteed @thick K.Type, @in_guaranteed Int) -> @out K, indices [%$0 : $Int : $Int], indices_equals @$sSiTH : $@convention(keypath_accessor_equals) (@in_guaranteed Int, @in_guaranteed Int) -> Bool, indices_hash @$sSiTh : $@convention(keypath_accessor_hash) (@in_guaranteed Int) -> Int) let _ = \K.Type.init(val: 2025) // CHECK: keypath $WritableKeyPath, (root $K.Type; gettable_property $K, id @$s8keypaths1KV3valACSi_tcfC : $@convention(method) (Int, @thin K.Type) -> K, getter @$s8keypaths1KV3valACSi_tcfcACmTkMA : $@convention(keypath_accessor_getter) (@in_guaranteed @thick K.Type, @in_guaranteed Int) -> @out K, indices [%$0 : $Int : $Int], indices_equals @$sSiTH : $@convention(keypath_accessor_equals) (@in_guaranteed Int, @in_guaranteed Int) -> Bool, indices_hash @$sSiTh : $@convention(keypath_accessor_hash) (@in_guaranteed Int) -> Int; stored_property #K.year : $Int) let _ = \K.Type.init(val: 2025).year // CHECK: keypath $KeyPath, (root $K.Type; gettable_property $K, id @$s8keypaths1KVACycfC : $@convention(method) (@thin K.Type) -> K, getter @$s8keypaths1KVACycfcACmTkMA : $@convention(keypath_accessor_getter) (@in_guaranteed @thick K.Type) -> @out K; gettable_property $Int, id @$s8keypaths1KVyS2icig : $@convention(method) (Int, K) -> Int, getter @$s8keypaths1KVyS2icipACTK : $@convention(keypath_accessor_getter) (@in_guaranteed K, @in_guaranteed Int) -> @out Int, indices [%$0 : $Int : $Int], indices_equals @$sSiTH : $@convention(keypath_accessor_equals) (@in_guaranteed Int, @in_guaranteed Int) -> Bool, indices_hash @$sSiTh : $@convention(keypath_accessor_hash) (@in_guaranteed Int) -> Int) let _ = \K.Type.init()[0] // CHECK: keypath $KeyPath Int>, (root $K; gettable_property $(Int, Int) -> Int, id @$s8keypaths1KV3addyS2i_Sitcvg : $@convention(method) (K) -> @owned @callee_guaranteed (Int, Int) -> Int, getter @$s8keypaths1KV3addyS2i_SitcvpACTK : $@convention(keypath_accessor_getter) (@in_guaranteed K) -> @out @callee_guaranteed @substituted <τ_0_0, τ_0_1, τ_0_2> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> @out τ_0_2 for ) let _ = \K.add // CHECK: keypath $WritableKeyPath Int> // CHECK-SAME: root $K; gettable_property $(Int) -> Int, id @$s8keypaths1KV3add4thisS2i_tF : $@convention(method) (Int, K) -> Int, getter @$s8keypaths1KV3add4thisS2i_tFACTkmu : $@convention(keypath_accessor_getter) (@in_guaranteed K) -> @out @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1 for ) let _ = \K.add(this:) // CHECK: keypath $WritableKeyPath, (root $K; gettable_property $Int, id @$s8keypaths1KV3add4thatS2i_tF : $@convention(method) (Int, K) -> Int, getter @$s8keypaths1KV3add4thatS2i_tFACTkMA : $@convention(keypath_accessor_getter) (@in_guaranteed K, @in_guaranteed Int) -> @out Int, indices [%$0 : $Int : $Int], indices_equals @$sSiTH : $@convention(keypath_accessor_equals) (@in_guaranteed Int, @in_guaranteed Int) -> Bool, indices_hash @$sSiTh : $@convention(keypath_accessor_hash) (@in_guaranteed Int) -> Int) let _ = \K.add(that: 1) // CHECK: keypath $WritableKeyPath Int> // CHECK-SAME: root $K.Type; gettable_property $(Int) -> Int, id @$s8keypaths1KV8subtractyS2iFZ : $@convention(method) (Int, @thin K.Type) -> Int, getter @$s8keypaths1KV8subtractyS2iFZACmTkmu : $@convention(keypath_accessor_getter) (@in_guaranteed @thick K.Type) -> @out @callee_guaranteed @substituted <τ_0_0, τ_0_1> (@in_guaranteed τ_0_0) -> @out τ_0_1 for ) let _ = \K.Type.subtract // CHECK: keypath $WritableKeyPath, (root $K.Type; gettable_property $Int, id @$s8keypaths1KV8subtractyS2iFZ : $@convention(method) (Int, @thin K.Type) -> Int, getter @$s8keypaths1KV8subtractyS2iFZACmTkMA : $@convention(keypath_accessor_getter) (@in_guaranteed @thick K.Type, @in_guaranteed Int) -> @out Int, indices [%$0 : $Int : $Int], indices_equals @$sSiTH : $@convention(keypath_accessor_equals) (@in_guaranteed Int, @in_guaranteed Int) -> Bool, indices_hash @$sSiTh : $@convention(keypath_accessor_hash) (@in_guaranteed Int) -> Int) let _ = \K.Type.subtract(1) // CHECK: keypath $WritableKeyPath Int> // CHECK-SAME: root $K; gettable_property $() -> Int, id @$s8keypaths1KV19nonisolatedNextYearSiyF : $@convention(method) (K) -> Int, getter @$s8keypaths1KV19nonisolatedNextYearSiyFACTkmu : $@convention(keypath_accessor_getter) (@in_guaranteed K) -> @out @callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for ) let _ = \K.nonisolatedNextYear // CHECK: keypath $WritableKeyPath, (root $K; gettable_property $Int, id @$s8keypaths1KV19nonisolatedNextYearSiyF : $@convention(method) (K) -> Int, getter @$s8keypaths1KV19nonisolatedNextYearSiyFACTkMA : $@convention(keypath_accessor_getter) (@in_guaranteed K) -> @out Int) let _ = \K.nonisolatedNextYear() // CHECK: keypath $WritableKeyPath, (root $K.Type; gettable_property $K, id @$s8keypaths1KV3valACSi_tcfC : $@convention(method) (Int, @thin K.Type) -> K, getter @$s8keypaths1KV3valACSi_tcfcACmTkMA : $@convention(keypath_accessor_getter) (@in_guaranteed @thick K.Type, @in_guaranteed Int) -> @out K, indices [%$0 : $Int : $Int], indices_equals @$sSiTH : $@convention(keypath_accessor_equals) (@in_guaranteed Int, @in_guaranteed Int) -> Bool, indices_hash @$sSiTh : $@convention(keypath_accessor_hash) (@in_guaranteed Int) -> Int; gettable_property $Int, id @$s8keypaths1KV19nonisolatedNextYearSiyF : $@convention(method) (K) -> Int, getter @$s8keypaths1KV19nonisolatedNextYearSiyFACTkMA : $@convention(keypath_accessor_getter) (@in_guaranteed K) -> @out Int) let _ = \K.Type.init(val:2025).nonisolatedNextYear() // CHECK: keypath $KeyPath, (root $K.Type; gettable_property $K, id @$s8keypaths1KV3valACSi_tcfC : $@convention(method) (Int, @thin K.Type) -> K, getter @$s8keypaths1KV3valACSi_tcfcACmTkMA : $@convention(keypath_accessor_getter) (@in_guaranteed @thick K.Type, @in_guaranteed Int) -> @out K, indices [%$0 : $Int : $Int], indices_equals @$sSiTH : $@convention(keypath_accessor_equals) (@in_guaranteed Int, @in_guaranteed Int) -> Bool, indices_hash @$sSiTh : $@convention(keypath_accessor_hash) (@in_guaranteed Int) -> Int; gettable_property $Int, id @$s8keypaths1KV19nonisolatedNextYearSiyF : $@convention(method) (K) -> Int, getter @$s8keypaths1KV19nonisolatedNextYearSiyFACTkMA : $@convention(keypath_accessor_getter) (@in_guaranteed K) -> @out Int; gettable_property $String, id @$sSzsE11descriptionSSvg : $@convention(method) <τ_0_0 where τ_0_0 : BinaryInteger> (@in_guaranteed τ_0_0) -> @owned String, getter @$sSzsE11descriptionSSvpSiTK : $@convention(keypath_accessor_getter) (@in_guaranteed Int) -> @out String, external #BinaryInteger.description) let _ = \K.Type.init(val:2025).nonisolatedNextYear().description // CHECK: keypath $WritableKeyPath, (root $K.Type; gettable_property $K, id @$s8keypaths1KV3valACSi_tcfC : $@convention(method) (Int, @thin K.Type) -> K, getter @$s8keypaths1KV3valACSi_tcfcACmTkMA : $@convention(keypath_accessor_getter) (@in_guaranteed @thick K.Type, @in_guaranteed Int) -> @out K, indices [%$0 : $Int : $Int], indices_equals @$sSiTH : $@convention(keypath_accessor_equals) (@in_guaranteed Int, @in_guaranteed Int) -> Bool, indices_hash @$sSiTh : $@convention(keypath_accessor_hash) (@in_guaranteed Int) -> Int; gettable_property $Int, id @$s8keypaths1KV19nonisolatedNextYearSiyF : $@convention(method) (K) -> Int, getter @$s8keypaths1KV19nonisolatedNextYearSiyFACTkMA : $@convention(keypath_accessor_getter) (@in_guaranteed K) -> @out Int; gettable_property $Int, id @$sSi6signumSiyF : $@convention(method) (Int) -> Int, getter @$sSi6signumSiyFSiTkMA : $@convention(keypath_accessor_getter) (@in_guaranteed Int) -> @out Int) let _ = \K.Type.init(val:2025).nonisolatedNextYear().signum() // CHECK: keypath $WritableKeyPath, (root $K; gettable_property $(), id @$s8keypaths1KV3foo13hashableParamyAA1JC_tF : $@convention(method) (@guaranteed J, K) -> (), getter @$s8keypaths1KV3foo13hashableParamyAA1JC_tFACTkMA : $@convention(keypath_accessor_getter) (@in_guaranteed K, @in_guaranteed J) -> @out (), indices [%$0 : $J : $J], indices_equals @$s8keypaths1JCTH : $@convention(keypath_accessor_equals) (@in_guaranteed J, @in_guaranteed J) -> Bool, indices_hash @$s8keypaths1JCTh : $@convention(keypath_accessor_hash) (@in_guaranteed J) -> Int) let hashableInstance = J() let _ = \K.foo(hashableParam: hashableInstance) // CHECK: keypath $WritableKeyPath String> // CHECK-SAME: root $L; gettable_property $() -> String, id @$s8keypaths1LV8describeSSyF : $@convention(method) (@guaranteed L) -> @owned String, getter @$s8keypaths1LV8describeSSyFACTkmu : $@convention(keypath_accessor_getter) (@in_guaranteed L) -> @out @callee_guaranteed @substituted <τ_0_0> () -> @out τ_0_0 for ) let _ = \L.describe // CHECK: keypath $WritableKeyPath, (root $L; gettable_property $String, id @$s8keypaths1LV8describeSSyF : $@convention(method) (@guaranteed L) -> @owned String, getter @$s8keypaths1LV8describeSSyFACTkMA : $@convention(keypath_accessor_getter) (@in_guaranteed L) -> @out String) let _ = \L.describe() } struct N { static let kelvin = 293 } class M { static var chanceRain = 10 static let isSunny = true private(set) static var isCloudy = false static subscript(day: Int) -> String { "Monday" } subscript(temp: Int) -> N.Type { N.self } static subscript(kelvinTemp: Int) -> N.Type { N.self } var degrees: N.Type? { return N.self } } // CHECK-LABEL: // test_metatype_keypaths() // CHECK-LABEL: sil hidden [ossa] @{{.*}} : $@convention(thin) () -> () { func test_metatype_keypaths() { // CHECK: keypath $ReferenceWritableKeyPath, (root $M.Type; settable_property $Int, id @$s8keypaths1MC10chanceRainSivgZ : $@convention(method) (@thick M.Type) -> Int, getter @$s8keypaths1MC10chanceRainSivpZACmTK : $@convention(keypath_accessor_getter) (@in_guaranteed @thick M.Type) -> @out Int, setter @$s8keypaths1MC10chanceRainSivpZACmTk : $@convention(keypath_accessor_setter) (@in_guaranteed Int, @in_guaranteed @thick M.Type) -> ()) let _: KeyPath = \M.Type.chanceRain // CHECK: keypath $KeyPath, (root $M.Type; gettable_property $Bool, id @$s8keypaths1MC7isSunnySbvgZ : $@convention(method) (@thick M.Type) -> Bool, getter @$s8keypaths1MC7isSunnySbvpZACmTK : $@convention(keypath_accessor_getter) (@in_guaranteed @thick M.Type) -> @out Bool) let _: KeyPath = \M.Type.isSunny // CHECK: keypath $ReferenceWritableKeyPath, (root $M.Type; settable_property $Bool, id @$s8keypaths1MC8isCloudySbvgZ : $@convention(method) (@thick M.Type) -> Bool, getter @$s8keypaths1MC8isCloudySbvpZACmTK : $@convention(keypath_accessor_getter) (@in_guaranteed @thick M.Type) -> @out Bool, setter @$s8keypaths1MC8isCloudySbvpZACmTk : $@convention(keypath_accessor_setter) (@in_guaranteed Bool, @in_guaranteed @thick M.Type) -> ()) let _: KeyPath = \M.Type.isCloudy // CHECK: keypath $KeyPath, (root $M.Type; gettable_property $String, id @$s8keypaths1MCySSSicigZ : $@convention(method) (Int, @thick M.Type) -> @owned String, getter @$s8keypaths1MCySSSicipZACmTK : $@convention(keypath_accessor_getter) (@in_guaranteed @thick M.Type, @in_guaranteed Int) -> @out String, indices [%$0 : $Int : $Int], indices_equals @$sSiTH : $@convention(keypath_accessor_equals) (@in_guaranteed Int, @in_guaranteed Int) -> Bool, indices_hash @$sSiTh : $@convention(keypath_accessor_hash) (@in_guaranteed Int) -> Int) (%{{.*}}) let _: KeyPath = \M.Type.[2] // CHECK: keypath $KeyPath, (root $M; gettable_property $N.Type, id #M.subscript!getter : (M) -> (Int) -> N.Type, getter @$s8keypaths1MCyAA1NVmSicipACTK : $@convention(keypath_accessor_getter) (@in_guaranteed M, @in_guaranteed Int) -> @out @thick N.Type, indices [%$0 : $Int : $Int], indices_equals @$sSiTH : $@convention(keypath_accessor_equals) (@in_guaranteed Int, @in_guaranteed Int) -> Bool, indices_hash @$sSiTh : $@convention(keypath_accessor_hash) (@in_guaranteed Int) -> Int) (%{{.*}}) let _: KeyPath = \M.[76] // CHECK: keypath $KeyPath, (root $M.Type; gettable_property $N.Type, id @$s8keypaths1MCyAA1NVmSicigZ : $@convention(method) (Int, @thick M.Type) -> @thin N.Type, getter @$s8keypaths1MCyAA1NVmSicipZACmTK : $@convention(keypath_accessor_getter) (@in_guaranteed @thick M.Type, @in_guaranteed Int) -> @out @thick N.Type, indices [%$0 : $Int : $Int], indices_equals @$sSiTH : $@convention(keypath_accessor_equals) (@in_guaranteed Int, @in_guaranteed Int) -> Bool, indices_hash @$sSiTh : $@convention(keypath_accessor_hash) (@in_guaranteed Int) -> Int) (%{{.*}}) let _: KeyPath = \M.Type.[76] // CHECK: keypath $KeyPath>, (root $M; gettable_property $Optional, id #M.degrees!getter : (M) -> () -> N.Type?, getter @$s8keypaths1MC7degreesAA1NVmSgvpACTK : $@convention(keypath_accessor_getter) (@in_guaranteed M) -> @out Optional<@thick N.Type>; optional_chain : $N.Type; gettable_property $Int, id @$s8keypaths1NV6kelvinSivgZ : $@convention(method) (@thin N.Type) -> Int, getter @$s8keypaths1NV6kelvinSivpZACmTK : $@convention(keypath_accessor_getter) (@in_guaranteed @thick N.Type) -> @out Int; optional_wrap : $Optional) let _: KeyPath = \.degrees?.kelvin // CHECK: keypath $KeyPath, (root $Int.Type; gettable_property $Int, id @$ss18AdditiveArithmeticPss27ExpressibleByIntegerLiteralRzrlE4zeroxvgZ : $@convention(method) <τ_0_0 where τ_0_0 : AdditiveArithmetic, τ_0_0 : ExpressibleByIntegerLiteral> (@thick τ_0_0.Type) -> @out τ_0_0, getter @$ss18AdditiveArithmeticPss27ExpressibleByIntegerLiteralRzrlE4zeroxvpZSimTK : $@convention(keypath_accessor_getter) (@in_guaranteed @thick Int.Type) -> @out Int, external #AdditiveArithmetic.zero) let _: KeyPath = \Int.Type.zero } // apple/swift#71423 protocol CodingKey {} struct URICoderCodingKey : CodingKey {} struct CodingStackEntry { var key: URICoderCodingKey } struct Test { var codingStack: [CodingStackEntry] // CHECK-LABEL: sil hidden [ossa] @{{.*}}codingPathAny var codingPathAny: [any CodingKey] { codingStack.map(\.key) } // CHECK: keypath $KeyPath, (root $CodingStackEntry; stored_property #CodingStackEntry.key : $URICoderCodingKey) // CHECK-LABEL: sil hidden [ossa] @{{.*}}codingPathOpt var codingPathOpt: [URICoderCodingKey?] { codingStack.map(\.key) } // CHECK: keypath $KeyPath, (root $CodingStackEntry; stored_property #CodingStackEntry.key : $URICoderCodingKey) } // rdar://123638701 - Make sure that optional chaining forces loads. func test_optional_chaining_with_function_conversion() { class Storage {} class Elements { var db: Storage = Storage() } class Source { var elements: Elements? = nil } func test(data: [Source]) { // CHECK: {{.*}} = keypath $KeyPath> _ = data.compactMap(\.elements?.db) // CHECK: {{.*}} = keypath $KeyPath _ = data.compactMap(\.elements!.db) } } protocol HasAlias { var id: Self.ID { get } typealias ID = Int } func testHasAlias() { _ = \HasAlias.id }