// RUN: %target-swift-emit-silgen -parse-stdlib -module-name keypaths %s | %FileCheck %s 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(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed C<τ_0_0>) -> @out S<τ_0_0>, // CHECK-SAME: setter @$s8keypaths1CC8nonfinalAA1SVyxGvpAA1PRzlACyxGTk : $@convention(thin) <τ_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(thin) <τ_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(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed C<τ_0_0>) -> @out S<τ_0_0>, // CHECK-SAME: setter @$s8keypaths1CC8observedAA1SVyxGvpAA1PRzlACyxGTk : $@convention(thin) <τ_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(thin) <τ_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(thin) <τ_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(thin) <τ_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(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed S<τ_0_0>) -> @out C<τ_0_0>, // CHECK-SAME: setter @$s8keypaths1SV8observedAA1CCyxGvpAA1PRzlACyxGTk : $@convention(thin) <τ_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(thin) <τ_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(thin) <τ_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(thin) <τ_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(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out String, // CHECK-SAME: setter @$s8keypaths1PP1ySSvpAaBRzlxTk : $@convention(thin) <τ_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(thin) (@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(thin) (@in_guaranteed SubscriptDefaults4, UnsafeRawPointer) -> @out Int, setter @$s8keypaths18SubscriptDefaults4V1x1yxx_xtcSjRzluipACSiTk : $@convention(thin) (@in_guaranteed Int, @inout SubscriptDefaults4, UnsafeRawPointer) -> (), indices [%$0 : $Int : $Int, %$1 : $Int : $Int], indices_equals @$sS2iTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sS2iTh : $@convention(thin) (UnsafeRawPointer) -> 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(thin) (@in_guaranteed SubscriptDefaults4, UnsafeRawPointer) -> @out Int, setter @$s8keypaths18SubscriptDefaults4V1x1yxx_xtcSjRzluipACSiTk : $@convention(thin) (@in_guaranteed Int, @inout SubscriptDefaults4, UnsafeRawPointer) -> (), indices [%$0 : $Int : $Int, %$1 : $Int : $Int], indices_equals @$sS2iTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sS2iTh : $@convention(thin) (UnsafeRawPointer) -> 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(thin) (@in_guaranteed SubscriptDefaults5, UnsafeRawPointer) -> @out String, setter @$s8keypaths18SubscriptDefaults5V1x1yxx_xtcs26ExpressibleByStringLiteralRzluipACSSTk : $@convention(thin) (@in_guaranteed String, @inout SubscriptDefaults5, UnsafeRawPointer) -> (), indices [%$0 : $String : $String, %$1 : $String : $String], indices_equals @$sS2STH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sS2STh : $@convention(thin) (UnsafeRawPointer) -> 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(thin) (@in_guaranteed SubscriptDefaults5, UnsafeRawPointer) -> @out String, setter @$s8keypaths18SubscriptDefaults5V1x1yxx_xtcs26ExpressibleByStringLiteralRzluipACSSTk : $@convention(thin) (@in_guaranteed String, @inout SubscriptDefaults5, UnsafeRawPointer) -> (), indices [%$0 : $String : $String, %$1 : $String : $String], indices_equals @$sS2STH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sS2STh : $@convention(thin) (UnsafeRawPointer) -> 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: keypath $KeyPath, (root $SubscriptVariadic1; gettable_property $Int, id @$s8keypaths18SubscriptVariadic1VyS2id_tcig : $@convention(method) (@guaranteed Array, SubscriptVariadic1) -> Int, getter @$s8keypaths18SubscriptVariadic1VyS2id_tcipACTK : $@convention(thin) (@in_guaranteed SubscriptVariadic1, UnsafeRawPointer) -> @out Int, indices [%$0 : $Array : $Array], indices_equals @$sSaySiGTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sSaySiGTh : $@convention(thin) (UnsafeRawPointer) -> Int) ([[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: keypath $KeyPath, (root $SubscriptVariadic1; gettable_property $Int, id @$s8keypaths18SubscriptVariadic1VyS2id_tcig : $@convention(method) (@guaranteed Array, SubscriptVariadic1) -> Int, getter @$s8keypaths18SubscriptVariadic1VyS2id_tcipACTK : $@convention(thin) (@in_guaranteed SubscriptVariadic1, UnsafeRawPointer) -> @out Int, indices [%$0 : $Array : $Array], indices_equals @$sSaySiGTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sSaySiGTh : $@convention(thin) (UnsafeRawPointer) -> Int) ([[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(thin) (@in_guaranteed SubscriptVariadic1, UnsafeRawPointer) -> @out Int, indices [%$0 : $Array : $Array], indices_equals @$sSaySiGTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sSaySiGTh : $@convention(thin) (UnsafeRawPointer) -> 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: 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(thin) (@in_guaranteed SubscriptVariadic2, UnsafeRawPointer) -> @out String, indices [%$0 : $Array : $Array], indices_equals @$sSaySSGTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sSaySSGTh : $@convention(thin) (UnsafeRawPointer) -> Int) ([[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 } // 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 }