Files
swift-mirror/test/SILGen/keypaths.swift
Arnold Schwaighofer 1d4497a599 SILVerifier: Fix keypath verification involving opaque return types
The SIL type of the keypath instruction is lowered in the function's
type expansion context, the various types involved in patterns are
unlowered AST types.

When verifying that the types matchup apply the type expansion to both
sides.

rdar://72134937
2020-12-10 13:52:08 -08:00

632 lines
29 KiB
Swift

// RUN: %target-swift-emit-silgen -disable-availability-checking -parse-stdlib -module-name keypaths %s | %FileCheck %s
import Swift
struct S<T> {
var x: T
let y: String
var z: C<T>
var computed: C<T> { fatalError() }
var observed: C<T> { didSet { fatalError() } }
var reabstracted: () -> ()
}
class C<T> {
final var x: T
final let y: String
final var z: S<T>
var nonfinal: S<T>
var computed: S<T> { fatalError() }
var observed: S<T> { didSet { fatalError() } }
final var reabstracted: () -> ()
init() { fatalError() }
}
extension C {
var `extension`: S<T> { 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<Int>, y: C<String>)
}
/* TODO: When we support superclass requirements on protocols, we should test
* this case as well.
protocol PoC : C<Int> {}
*/
// CHECK-LABEL: sil hidden [ossa] @{{.*}}storedProperties
func storedProperties<T>(_: T) {
// CHECK: keypath $WritableKeyPath<S<T>, T>, <τ_0_0> (root $S<τ_0_0>; stored_property #S.x : $τ_0_0) <T>
_ = \S<T>.x
// CHECK: keypath $KeyPath<S<T>, String>, <τ_0_0> (root $S<τ_0_0>; stored_property #S.y : $String) <T>
_ = \S<T>.y
// CHECK: keypath $ReferenceWritableKeyPath<S<T>, T>, <τ_0_0> (root $S<τ_0_0>; stored_property #S.z : $C<τ_0_0>; stored_property #C.x : $τ_0_0) <T>
_ = \S<T>.z.x
// CHECK: keypath $ReferenceWritableKeyPath<C<T>, T>, <τ_0_0> (root $C<τ_0_0>; stored_property #C.x : $τ_0_0) <T>
_ = \C<T>.x
// CHECK: keypath $KeyPath<C<T>, String>, <τ_0_0> (root $C<τ_0_0>; stored_property #C.y : $String) <T>
_ = \C<T>.y
// CHECK: keypath $ReferenceWritableKeyPath<C<T>, T>, <τ_0_0> (root $C<τ_0_0>; stored_property #C.z : $S<τ_0_0>; stored_property #S.x : $τ_0_0) <T>
_ = \C<T>.z.x
// CHECK: keypath $KeyPath<C<T>, 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) <T>
_ = \C<T>.z.z.y
}
// CHECK-LABEL: sil hidden [ossa] @{{.*}}computedProperties
func computedProperties<T: P>(_: T) {
// CHECK: keypath $ReferenceWritableKeyPath<C<T>, S<T>>, <τ_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 : <T> (C<T>) -> () -> S<T>,
// 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: ) <T>
_ = \C<T>.nonfinal
// CHECK: keypath $KeyPath<C<T>, S<T>>, <τ_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 : <T> (C<T>) -> () -> S<T>,
// CHECK-SAME: getter @$s8keypaths1CC8computedAA1SVyxGvpAA1PRzlACyxGTK : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed C<τ_0_0>) -> @out S<τ_0_0>
// CHECK-SAME: ) <T>
_ = \C<T>.computed
// CHECK: keypath $ReferenceWritableKeyPath<C<T>, S<T>>, <τ_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 : <T> (C<T>) -> () -> S<T>,
// 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: ) <T>
_ = \C<T>.observed
_ = \C<T>.nonfinal.x
_ = \C<T>.computed.x
_ = \C<T>.observed.x
_ = \C<T>.z.computed
_ = \C<T>.z.observed
_ = \C<T>.observed.x
// CHECK: keypath $ReferenceWritableKeyPath<C<T>, () -> ()>, <τ_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: ) <T>
_ = \C<T>.reabstracted
// CHECK: keypath $KeyPath<S<T>, C<T>>, <τ_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: ) <T>
_ = \S<T>.computed
// CHECK: keypath $WritableKeyPath<S<T>, C<T>>, <τ_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: ) <T>
_ = \S<T>.observed
_ = \S<T>.z.nonfinal
_ = \S<T>.z.computed
_ = \S<T>.z.observed
_ = \S<T>.computed.x
_ = \S<T>.computed.y
// CHECK: keypath $WritableKeyPath<S<T>, () -> ()>, <τ_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: ) <T>
_ = \S<T>.reabstracted
// CHECK: keypath $KeyPath<T, Int>, <τ_0_0 where τ_0_0 : P> (
// CHECK-SAME: root $τ_0_0;
// CHECK-SAME: gettable_property $Int,
// CHECK-SAME: id #P.x!getter : <Self where Self : P> (Self) -> () -> Int,
// CHECK-SAME: getter @$s8keypaths1PP1xSivpAaBRzlxTK : $@convention(thin) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> @out Int
// CHECK-SAME: ) <T>
_ = \T.x
// CHECK: keypath $WritableKeyPath<T, String>, <τ_0_0 where τ_0_0 : P> (
// CHECK-SAME: root $τ_0_0;
// CHECK-SAME: settable_property $String,
// CHECK-SAME: id #P.y!getter : <Self where Self : P> (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>
_ = \T.y
// CHECK: keypath $KeyPath<T, String>, <τ_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<Concrete, String>, (
// CHECK-SAME: gettable_property $String,
// CHECK-SAME: id @$s8keypaths1PPAAE1zSSvg
// CHECK-SAME: getter @$s8keypaths1PPAAE1zSSvpAA8ConcreteVTK : $@convention(thin) (@in_guaranteed Concrete) -> @out String
_ = \Concrete.z
_ = \S<Concrete>.computed
}
class AA<T> {
var a: Int { get { return 0 } set { } }
}
class BB<U, V>: AA<V> {
}
func keyPathForInheritedMember() {
_ = \BB<Int, String>.a
}
func keyPathForExistentialMember() {
_ = \P.x
_ = \P.y
_ = \P.z
_ = \P.w
}
struct OptionalFields {
var x: S<Int>?
}
struct OptionalFields2 {
var y: OptionalFields?
}
// CHECK-LABEL: sil hidden [ossa] @$s8keypaths18keyPathForOptionalyyF
func keyPathForOptional() {
// CHECK: keypath $WritableKeyPath<OptionalFields, S<Int>>, (
// CHECK-SAME: stored_property #OptionalFields.x : $Optional<S<Int>>;
// CHECK-SAME: optional_force : $S<Int>)
_ = \OptionalFields.x!
// CHECK: keypath $KeyPath<OptionalFields, Optional<String>>, (
// CHECK-SAME: stored_property #OptionalFields.x : $Optional<S<Int>>;
// CHECK-SAME: optional_chain : $S<Int>;
// CHECK-SAME: stored_property #S.y : $String;
// CHECK-SAME: optional_wrap : $Optional<String>)
_ = \OptionalFields.x?.y
// CHECK: keypath $KeyPath<OptionalFields2, Optional<S<Int>>>, (
// CHECK-SAME: root $OptionalFields2;
// CHECK-SAME: stored_property #OptionalFields2.y : $Optional<OptionalFields>;
// CHECK-SAME: optional_chain : $OptionalFields;
// CHECK-SAME: stored_property #OptionalFields.x : $Optional<S<Int>>)
_ = \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<StorageQualified, Optional<StorageQualified>>,
// CHECK-SAME: settable_property $Optional<StorageQualified>, id #StorageQualified.tooWeak!getter
_ = \StorageQualified.tooWeak
// CHECK: = keypath $ReferenceWritableKeyPath<StorageQualified, StorageQualified>,
// CHECK-SAME: settable_property $StorageQualified, id #StorageQualified.disowned!getter
_ = \StorageQualified.disowned
// CHECK: = keypath $ReferenceWritableKeyPath<FinalStorageQualified, Optional<StorageQualified>>,
// CHECK-SAME: settable_property $Optional<StorageQualified>, id ##FinalStorageQualified.tooWeak
_ = \FinalStorageQualified.tooWeak
// CHECK: = keypath $ReferenceWritableKeyPath<FinalStorageQualified, StorageQualified>,
// 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<IUOProperty, Int>,
// CHECK-SAME: stored_property #IUOProperty.iuo
// CHECK-SAME: optional_force
// CHECK-SAME: stored_property #IUOBlob.x
_ = \IUOProperty.iuo.x
// CHECK: = keypath $WritableKeyPath<IUOProperty, Int>,
// 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<T> {
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<U>(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<T : Numeric>(x x: T, y y: T = 0) -> T {
get { fatalError() }
set { fatalError() }
}
}
struct SubscriptDefaults5 {
subscript<T : ExpressibleByStringLiteral>(x x: T, y y: T = #function) -> T {
get { fatalError() }
set { fatalError() }
}
}
// CHECK-LABEL: sil hidden [ossa] @{{.*}}10subscripts1x1y1syx_q_SStSHRzSHR_r0_lF
func subscripts<T: Hashable, U: Hashable>(x: T, y: U, s: String) {
_ = \Subscripts<T>.[]
_ = \Subscripts<T>.[generic: x]
_ = \Subscripts<T>.[concrete: s]
_ = \Subscripts<T>.[s, s]
_ = \Subscripts<T>.[subGeneric: s]
_ = \Subscripts<T>.[subGeneric: x]
_ = \Subscripts<T>.[subGeneric: y]
_ = \Subscripts<U>.[]
_ = \Subscripts<U>.[generic: y]
_ = \Subscripts<U>.[concrete: s]
_ = \Subscripts<U>.[s, s]
_ = \Subscripts<U>.[subGeneric: s]
_ = \Subscripts<U>.[subGeneric: x]
_ = \Subscripts<U>.[subGeneric: y]
_ = \Subscripts<String>.[]
_ = \Subscripts<String>.[generic: s]
_ = \Subscripts<String>.[concrete: s]
_ = \Subscripts<String>.[s, s]
_ = \Subscripts<String>.[subGeneric: s]
_ = \Subscripts<String>.[subGeneric: x]
_ = \Subscripts<String>.[subGeneric: y]
_ = \Subscripts<T>.[s, s].count
_ = \Subscripts<T>.[Bass()]
_ = \Subscripts<T>.[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<SubscriptDefaults4, Int>, (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]]<Int>([[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<SubscriptDefaults4, Int>, (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<SubscriptDefaults5, String>, (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<SubscriptDefaults5, String>, (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<T : ExpressibleByStringLiteral>(x: T...) -> T { x[0] }
}
struct SubscriptVariadic3<T : ExpressibleByStringLiteral> {
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]]<Int>([[ARR_COUNT]])
// CHECK: ([[ARR:%[0-9]+]], %{{[0-9]+}}) = destructure_tuple [[MAKE_ARR]] : $(Array<Int>, Builtin.RawPointer)
// CHECK: [[FIN_REF:%[0-9]+]] = function_ref @$ss27_finalizeUninitializedArrayySayxGABnlF
// CHECK: [[FIN_ARR:%[0-9]+]] = apply [[FIN_REF]]<Int>([[ARR]])
// CHECK: keypath $KeyPath<SubscriptVariadic1, Int>, (root $SubscriptVariadic1; gettable_property $Int, id @$s8keypaths18SubscriptVariadic1VyS2id_tcig : $@convention(method) (@guaranteed Array<Int>, SubscriptVariadic1) -> Int, getter @$s8keypaths18SubscriptVariadic1VyS2id_tcipACTK : $@convention(thin) (@in_guaranteed SubscriptVariadic1, UnsafeRawPointer) -> @out Int, indices [%$0 : $Array<Int> : $Array<Int>], indices_equals @$sSaySiGTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sSaySiGTh : $@convention(thin) (UnsafeRawPointer) -> 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]]<Int>([[ARR_COUNT]])
// CHECK: ([[ARR:%[0-9]+]], %{{[0-9]+}}) = destructure_tuple [[MAKE_ARR]] : $(Array<Int>, Builtin.RawPointer)
// CHECK: [[FIN_REF:%[0-9]+]] = function_ref @$ss27_finalizeUninitializedArrayySayxGABnlF
// CHECK: [[FIN_ARR:%[0-9]+]] = apply [[FIN_REF]]<Int>([[ARR]])
// CHECK: keypath $KeyPath<SubscriptVariadic1, Int>, (root $SubscriptVariadic1; gettable_property $Int, id @$s8keypaths18SubscriptVariadic1VyS2id_tcig : $@convention(method) (@guaranteed Array<Int>, SubscriptVariadic1) -> Int, getter @$s8keypaths18SubscriptVariadic1VyS2id_tcipACTK : $@convention(thin) (@in_guaranteed SubscriptVariadic1, UnsafeRawPointer) -> @out Int, indices [%$0 : $Array<Int> : $Array<Int>], indices_equals @$sSaySiGTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sSaySiGTh : $@convention(thin) (UnsafeRawPointer) -> 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]]<Int>([[ARR_COUNT]])
// CHECK: ([[ARR:%[0-9]+]], %{{[0-9]+}}) = destructure_tuple [[MAKE_ARR]] : $(Array<Int>, Builtin.RawPointer)
// CHECK: keypath $KeyPath<SubscriptVariadic1, Int>, (root $SubscriptVariadic1; gettable_property $Int, id @$s8keypaths18SubscriptVariadic1VyS2id_tcig : $@convention(method) (@guaranteed Array<Int>, SubscriptVariadic1) -> Int, getter @$s8keypaths18SubscriptVariadic1VyS2id_tcipACTK : $@convention(thin) (@in_guaranteed SubscriptVariadic1, UnsafeRawPointer) -> @out Int, indices [%$0 : $Array<Int> : $Array<Int>], 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]]<String>([[ARR_COUNT]])
// CHECK: ([[ARR:%[0-9]+]], %{{[0-9]+}}) = destructure_tuple [[MAKE_ARR]] : $(Array<String>, Builtin.RawPointer)
// CHECK: [[FIN_REF:%[0-9]+]] = function_ref @$ss27_finalizeUninitializedArrayySayxGABnlF
// CHECK: [[FIN_ARR:%[0-9]+]] = apply [[FIN_REF]]<String>([[ARR]])
// CHECK: keypath $KeyPath<SubscriptVariadic2, String>, (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<String> : $Array<String>], indices_equals @$sSaySSGTH : $@convention(thin) (UnsafeRawPointer, UnsafeRawPointer) -> Bool, indices_hash @$sSaySSGTh : $@convention(thin) (UnsafeRawPointer) -> Int) ([[FIN_ARR]])
_ = \SubscriptVariadic2.["", #function]
_ = \SubscriptVariadic3<String>.[""]
_ = \SubscriptVariadic3<String>.["", "1"]
_ = \SubscriptVariadic3<String>.[]
}
// CHECK-LABEL: sil hidden [ossa] @{{.*}}subclass_generics
func subclass_generics<T: C<Int>, U: C<V>, 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<Int> & P).x
_ = \(C<Int> & P).z
_ = \(C<Int> & P).computed
_ = \(C<Int> & P).extension
_ = \(C<V> & P).x
_ = \(C<V> & P).z
_ = \(C<V> & P).computed
_ = \(C<V> & 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>(_: T) {
// CHECK: keypath $WritableKeyPath<T, T>, <τ_0_0> ({{.*}}root $τ_0_0) <T>
let _: WritableKeyPath<T, T> = \T.self
// CHECK: keypath $WritableKeyPath<Array<T>, Array<T>>, <τ_0_0> ({{.*}}root $Array<τ_0_0>) <T>
let _: WritableKeyPath<[T], [T]> = \[T].self
// CHECK: keypath $WritableKeyPath<String, String>, ({{.*}}root $String)
let _: WritableKeyPath<String, String> = \String.self
}
// CHECK-LABEL: sil hidden [ossa] @{{.*}}tuples
func tuples(_: T) {
// CHECK: keypath $WritableKeyPath<T, Int>, (root $T; stored_property #T.a : $(Int, String); tuple_element #0 : $Int)
let _: WritableKeyPath<T, Int> = \T.a.0
// CHECK: keypath $WritableKeyPath<T, String>, (root $T; stored_property #T.a : $(Int, String); tuple_element #1 : $String)
let _: WritableKeyPath<T, String> = \T.a.1
// CHECK: keypath $KeyPath<T, String>, (root $T; stored_property #T.b : $(f: String, g: Int); tuple_element #0 : $String)
let _: KeyPath<T, String> = \T.b.f
// CHECK: keypath $KeyPath<T, Int>, (root $T; stored_property #T.b : $(f: String, g: Int); tuple_element #1 : $Int)
let _: KeyPath<T, Int> = \T.b.g
// CHECK: keypath $KeyPath<T, C<Int>>, (root $T; stored_property #T.c : $(x: C<Int>, y: C<String>); tuple_element #0 : $C<Int>)
let _: KeyPath<T, C<Int>> = \T.c.x
// CHECK: keypath $KeyPath<T, C<String>>, (root $T; stored_property #T.c : $(x: C<Int>, y: C<String>); tuple_element #1 : $C<String>)
let _: KeyPath<T, C<String>> = \T.c.y
// CHECK: keypath $ReferenceWritableKeyPath<T, Int>, (root $T; stored_property #T.c : $(x: C<Int>, y: C<String>); tuple_element #0 : $C<Int>; stored_property #C.x : $Int)
let _: ReferenceWritableKeyPath<T, Int> = \T.c.x.x
// CHECK: keypath $KeyPath<T, String>, (root $T; stored_property #T.c : $(x: C<Int>, y: C<String>); tuple_element #0 : $C<Int>; stored_property #C.y : $String)
let _: KeyPath<T, String> = \T.c.x.y
}
// CHECK-LABEL: sil hidden [ossa] @{{.*}}tuples_generic
func tuples_generic<T, U, V>(_: T, _: U, _: V) {
typealias TUC = (T, U, C<V>)
// CHECK: keypath $WritableKeyPath<(T, U, C<V>), T>, <τ_0_0, τ_0_1, τ_0_2> (root $(τ_0_0, τ_0_1, C<τ_0_2>); tuple_element #0 : $τ_0_0) <T, U, V>
let _: WritableKeyPath<TUC, T> = \TUC.0
// CHECK: keypath $WritableKeyPath<(T, U, C<V>), U>, <τ_0_0, τ_0_1, τ_0_2> (root $(τ_0_0, τ_0_1, C<τ_0_2>); tuple_element #1 : $τ_0_1) <T, U, V>
let _: WritableKeyPath<TUC, U> = \TUC.1
// CHECK: keypath $ReferenceWritableKeyPath<(T, U, C<V>), 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) <T, U, V>
let _: ReferenceWritableKeyPath<TUC, V> = \TUC.2.x
// CHECK: keypath $KeyPath<(T, U, C<V>), 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) <T, U, V>
let _: KeyPath<TUC, String> = \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<SomeType>.y
_ = \S<SomeType>.z.x
_ = \C<SomeType>.x
_ = \C<SomeType>.y
_ = \C<SomeType>.z.x
_ = \C<SomeType>.z.z.y
_ = \C<SomeType>.nonfinal
_ = \C<SomeType>.computed
_ = \C<SomeType>.observed
_ = \C<SomeType>.nonfinal.x
_ = \C<SomeType>.computed.x
_ = \C<SomeType>.observed.x
_ = \C<SomeType>.z.computed
_ = \C<SomeType>.z.observed
_ = \C<SomeType>.observed.x
_ = \C<SomeType>.reabstracted
_ = \S<SomeType>.computed
_ = \S<SomeType>.observed
_ = \S<SomeType>.z.nonfinal
_ = \S<SomeType>.z.computed
_ = \S<SomeType>.z.observed
_ = \S<SomeType>.computed.x
_ = \S<SomeType>.computed.y
_ = \S<SomeType>.reabstracted
}
}