// RUN: %target-swift-frontend -typecheck -parse-as-library %s -verify struct Sub: Hashable { static func ==(_: Sub, _: Sub) -> Bool { return true } var hashValue: Int { return 0 } } struct OptSub: Hashable { static func ==(_: OptSub, _: OptSub) -> Bool { return true } var hashValue: Int { return 0 } } struct NonHashableSub {} struct Prop { subscript(sub: Sub) -> A { get { return A() } set { } } subscript(optSub: OptSub) -> A? { get { return A() } set { } } subscript(nonHashableSub: NonHashableSub) -> A { get { return A() } set { } } subscript(a: Sub, b: Sub) -> A { get { return A() } set { } } subscript(a: Sub, b: NonHashableSub) -> A { get { return A() } set { } } var nonMutatingProperty: B { get { fatalError() } nonmutating set { fatalError() } } } struct A: Hashable { init() { fatalError() } var property: Prop var optProperty: Prop? let optLetProperty: Prop? subscript(sub: Sub) -> A { get { return self } set { } } static func ==(_: A, _: A) -> Bool { fatalError() } var hashValue: Int { fatalError() } } struct B {} struct C { var value: T subscript() -> T { get { return value } } subscript(sub: Sub) -> T { get { return value } set { } } subscript(sub: U) -> U { get { return sub } set { } } subscript(noHashableConstraint sub: X) -> X { get { return sub } set { } } } extension Array where Element == A { var property: Prop { fatalError() } } protocol P { var member: String { get } } extension B : P { var member : String { return "Member Value" } } struct Exactly {} func expect(_ x: inout T, toHaveType _: Exactly.Type) {} func testKeyPath(sub: Sub, optSub: OptSub, nonHashableSub: NonHashableSub, x: Int) { var a = \A.property expect(&a, toHaveType: Exactly>.self) var b = \A.[sub] expect(&b, toHaveType: Exactly>.self) var c = \A.[sub].property expect(&c, toHaveType: Exactly>.self) var d = \A.optProperty? expect(&d, toHaveType: Exactly>.self) var e = \A.optProperty?[sub] expect(&e, toHaveType: Exactly>.self) var f = \A.optProperty! expect(&f, toHaveType: Exactly>.self) var g = \A.property[optSub]?.optProperty![sub] expect(&g, toHaveType: Exactly>.self) var h = \[A].property expect(&h, toHaveType: Exactly>.self) var i = \[A].property.nonMutatingProperty expect(&i, toHaveType: Exactly>.self) var j = \[A].[x] expect(&j, toHaveType: Exactly>.self) var k = \[A: B].[A()] expect(&k, toHaveType: Exactly>.self) var l = \C.value expect(&l, toHaveType: Exactly, A>>.self) // expected-error@+1{{generic parameter 'T' could not be inferred}} _ = \C.value // expected-error@+1{{}} _ = \(() -> ()).noMember let _: PartialKeyPath = \.property let _: KeyPath = \.property let _: WritableKeyPath = \.property // expected-error@+1{{ambiguous}} (need to improve diagnostic) let _: ReferenceWritableKeyPath = \.property // FIXME: shouldn't be ambiguous // expected-error@+1{{ambiguous}} let _: PartialKeyPath = \.[sub] let _: KeyPath = \.[sub] let _: WritableKeyPath = \.[sub] // expected-error@+1{{ambiguous}} (need to improve diagnostic) let _: ReferenceWritableKeyPath = \.[sub] let _: PartialKeyPath = \.optProperty? let _: KeyPath = \.optProperty? // expected-error@+1{{cannot convert}} let _: WritableKeyPath = \.optProperty? // expected-error@+1{{cannot convert}} let _: ReferenceWritableKeyPath = \.optProperty? let _: PartialKeyPath = \.optProperty?[sub] let _: KeyPath = \.optProperty?[sub] // expected-error@+1{{cannot convert}} let _: WritableKeyPath = \.optProperty?[sub] // expected-error@+1{{cannot convert}} let _: ReferenceWritableKeyPath = \.optProperty?[sub] let _: KeyPath = \.optProperty! let _: KeyPath = \.optLetProperty! let _: KeyPath = \.property[optSub]?.optProperty! let _: KeyPath = \.property[optSub]?.optProperty![sub] let _: PartialKeyPath> = \.value let _: KeyPath, A> = \.value let _: WritableKeyPath, A> = \.value // expected-error@+1{{ambiguous}} (need to improve diagnostic) let _: ReferenceWritableKeyPath, A> = \.value let _: PartialKeyPath> = \C.value let _: KeyPath, A> = \C.value let _: WritableKeyPath, A> = \C.value // expected-error@+1{{cannot convert}} let _: ReferenceWritableKeyPath, A> = \C.value let _: PartialKeyPath = \.nonMutatingProperty let _: KeyPath = \.nonMutatingProperty let _: WritableKeyPath = \.nonMutatingProperty let _: ReferenceWritableKeyPath = \.nonMutatingProperty var m = [\A.property, \A.[sub], \A.optProperty!] expect(&m, toHaveType: Exactly<[PartialKeyPath]>.self) // FIXME: shouldn't be ambiguous // expected-error@+1{{ambiguous}} var n = [\A.property, \.optProperty, \.[sub], \.optProperty!] expect(&n, toHaveType: Exactly<[PartialKeyPath]>.self) // FIXME: shouldn't be ambiguous // expected-error@+1{{ambiguous}} let _: [PartialKeyPath] = [\.property, \.optProperty, \.[sub], \.optProperty!] var o = [\A.property, \C.value] expect(&o, toHaveType: Exactly<[AnyKeyPath]>.self) let _: AnyKeyPath = \A.property let _: AnyKeyPath = \C.value let _: AnyKeyPath = \.property // expected-error{{ambiguous}} let _: AnyKeyPath = \C.value // expected-error{{cannot convert}} (need to improve diagnostic) let _: AnyKeyPath = \.value // expected-error{{ambiguous}} let _ = \Prop.[nonHashableSub] // expected-error{{subscript index of type 'NonHashableSub' in a key path must be Hashable}} let _ = \Prop.[sub, sub] let _ = \Prop.[sub, nonHashableSub] // expected-error{{subscript index of type 'NonHashableSub' in a key path must be Hashable}} let _ = \C.[] let _ = \C.[sub] let _ = \C.[noHashableConstraint: sub] let _ = \C.[noHashableConstraint: nonHashableSub] // expected-error{{subscript index of type 'NonHashableSub' in a key path must be Hashable}} } func testKeyPathInGenericContext(hashable: H, anything: X) { let _ = \C.[hashable] let _ = \C.[noHashableConstraint: hashable] let _ = \C.[noHashableConstraint: anything] // expected-error{{subscript index of type 'X' in a key path must be Hashable}} } func testDisembodiedStringInterpolation(x: Int) { \(x) // expected-error{{string interpolation}} expected-error{{}} \(x, radix: 16) // expected-error{{string interpolation}} expected-error{{}} _ = \(Int, Int).0 // expected-error{{cannot reference tuple elements}} } func testNoComponents() { let _: KeyPath = \A // expected-error{{must have at least one component}} let _: KeyPath = \C // expected-error{{must have at least one component}} expected-error{{}} } struct TupleStruct { var unlabeled: (Int, String) var labeled: (foo: Int, bar: String) } func tupleComponent() { // TODO: Customized diagnostic let _ = \(Int, String).0 // expected-error{{}} let _ = \(Int, String).1 // expected-error{{}} let _ = \TupleStruct.unlabeled.0 // expected-error{{}} let _ = \TupleStruct.unlabeled.1 // expected-error{{}} let _ = \(foo: Int, bar: String).0 // expected-error{{}} let _ = \(foo: Int, bar: String).1 // expected-error{{}} let _ = \(foo: Int, bar: String).foo // expected-error{{}} let _ = \(foo: Int, bar: String).bar // expected-error{{}} let _ = \TupleStruct.labeled.0 // expected-error{{}} let _ = \TupleStruct.labeled.1 // expected-error{{}} let _ = \TupleStruct.labeled.foo // expected-error{{}} let _ = \TupleStruct.labeled.bar // expected-error{{}} } struct Z { } func testKeyPathSubscript(readonly: Z, writable: inout Z, kp: KeyPath, wkp: WritableKeyPath, rkp: ReferenceWritableKeyPath) { var sink: Int sink = readonly[keyPath: kp] sink = writable[keyPath: kp] sink = readonly[keyPath: wkp] sink = writable[keyPath: wkp] sink = readonly[keyPath: rkp] sink = writable[keyPath: rkp] readonly[keyPath: kp] = sink // expected-error{{cannot assign to immutable}} writable[keyPath: kp] = sink // expected-error{{cannot assign to immutable}} readonly[keyPath: wkp] = sink // expected-error{{cannot assign to immutable}} writable[keyPath: wkp] = sink readonly[keyPath: rkp] = sink writable[keyPath: rkp] = sink let pkp: PartialKeyPath = rkp var anySink1 = readonly[keyPath: pkp] expect(&anySink1, toHaveType: Exactly.self) var anySink2 = writable[keyPath: pkp] expect(&anySink2, toHaveType: Exactly.self) readonly[keyPath: pkp] = anySink1 // expected-error{{cannot assign to immutable}} writable[keyPath: pkp] = anySink2 // expected-error{{cannot assign to immutable}} let akp: AnyKeyPath = pkp var anyqSink1 = readonly[keyPath: akp] expect(&anyqSink1, toHaveType: Exactly.self) var anyqSink2 = writable[keyPath: akp] expect(&anyqSink2, toHaveType: Exactly.self) readonly[keyPath: akp] = anyqSink1 // expected-error{{cannot assign to immutable}} writable[keyPath: akp] = anyqSink2 // expected-error{{cannot assign to immutable}} } struct ZwithSubscript { subscript(keyPath kp: KeyPath) -> Int { return 0 } subscript(keyPath kp: WritableKeyPath) -> Int { return 0 } subscript(keyPath kp: ReferenceWritableKeyPath) -> Int { return 0 } subscript(keyPath kp: PartialKeyPath) -> Any { return 0 } } struct NotZ {} func testKeyPathSubscript(readonly: ZwithSubscript, writable: inout ZwithSubscript, wrongType: inout NotZ, kp: KeyPath, wkp: WritableKeyPath, rkp: ReferenceWritableKeyPath) { var sink: Int sink = readonly[keyPath: kp] sink = writable[keyPath: kp] sink = readonly[keyPath: wkp] sink = writable[keyPath: wkp] sink = readonly[keyPath: rkp] sink = writable[keyPath: rkp] readonly[keyPath: kp] = sink // expected-error{{cannot assign through subscript: subscript is get-only}} writable[keyPath: kp] = sink // expected-error{{cannot assign through subscript: subscript is get-only}} readonly[keyPath: wkp] = sink // expected-error{{cannot assign through subscript: subscript is get-only}} // FIXME: silently falls back to keypath application, which seems inconsistent writable[keyPath: wkp] = sink // FIXME: silently falls back to keypath application, which seems inconsistent readonly[keyPath: rkp] = sink // FIXME: silently falls back to keypath application, which seems inconsistent writable[keyPath: rkp] = sink let pkp: PartialKeyPath = rkp var anySink1 = readonly[keyPath: pkp] expect(&anySink1, toHaveType: Exactly.self) var anySink2 = writable[keyPath: pkp] expect(&anySink2, toHaveType: Exactly.self) readonly[keyPath: pkp] = anySink1 // expected-error{{cannot assign through subscript: subscript is get-only}} writable[keyPath: pkp] = anySink2 // expected-error{{cannot assign through subscript: subscript is get-only}} let akp: AnyKeyPath = pkp var anyqSink1 = readonly[keyPath: akp] expect(&anyqSink1, toHaveType: Exactly.self) var anyqSink2 = writable[keyPath: akp] expect(&anyqSink2, toHaveType: Exactly.self) // FIXME: silently falls back to keypath application, which seems inconsistent readonly[keyPath: akp] = anyqSink1 // expected-error{{cannot assign to immutable}} // FIXME: silently falls back to keypath application, which seems inconsistent writable[keyPath: akp] = anyqSink2 // expected-error{{cannot assign to immutable}} _ = wrongType[keyPath: kp] // expected-error{{cannot be applied}} _ = wrongType[keyPath: wkp] // expected-error{{cannot be applied}} _ = wrongType[keyPath: rkp] // expected-error{{cannot be applied}} _ = wrongType[keyPath: pkp] // expected-error{{cannot be applied}} _ = wrongType[keyPath: akp] } func testKeyPathSubscriptMetatype(readonly: Z.Type, writable: inout Z.Type, kp: KeyPath, wkp: WritableKeyPath, rkp: ReferenceWritableKeyPath) { var sink: Int sink = readonly[keyPath: kp] sink = writable[keyPath: kp] sink = readonly[keyPath: wkp] sink = writable[keyPath: wkp] sink = readonly[keyPath: rkp] sink = writable[keyPath: rkp] readonly[keyPath: kp] = sink // expected-error{{cannot assign to immutable}} writable[keyPath: kp] = sink // expected-error{{cannot assign to immutable}} readonly[keyPath: wkp] = sink // expected-error{{cannot assign to immutable}} writable[keyPath: wkp] = sink readonly[keyPath: rkp] = sink writable[keyPath: rkp] = sink } func testKeyPathSubscriptTuple(readonly: (Z,Z), writable: inout (Z,Z), kp: KeyPath<(Z,Z), Int>, wkp: WritableKeyPath<(Z,Z), Int>, rkp: ReferenceWritableKeyPath<(Z,Z), Int>) { var sink: Int sink = readonly[keyPath: kp] sink = writable[keyPath: kp] sink = readonly[keyPath: wkp] sink = writable[keyPath: wkp] sink = readonly[keyPath: rkp] sink = writable[keyPath: rkp] readonly[keyPath: kp] = sink // expected-error{{cannot assign to immutable}} writable[keyPath: kp] = sink // expected-error{{cannot assign to immutable}} readonly[keyPath: wkp] = sink // expected-error{{cannot assign to immutable}} writable[keyPath: wkp] = sink readonly[keyPath: rkp] = sink writable[keyPath: rkp] = sink } func testKeyPathSubscriptLValue(base: Z, kp: inout KeyPath) { _ = base[keyPath: kp] } func testKeyPathSubscriptExistentialBase(concreteBase: inout B, existentialBase: inout P, kp: KeyPath, wkp: WritableKeyPath, rkp: ReferenceWritableKeyPath, pkp: PartialKeyPath

, s: String) { _ = concreteBase[keyPath: kp] _ = concreteBase[keyPath: wkp] _ = concreteBase[keyPath: rkp] _ = concreteBase[keyPath: pkp] concreteBase[keyPath: kp] = s // expected-error{{}} concreteBase[keyPath: wkp] = s // expected-error{{}} concreteBase[keyPath: rkp] = s concreteBase[keyPath: pkp] = s // expected-error{{}} _ = existentialBase[keyPath: kp] _ = existentialBase[keyPath: wkp] _ = existentialBase[keyPath: rkp] _ = existentialBase[keyPath: pkp] existentialBase[keyPath: kp] = s // expected-error{{}} existentialBase[keyPath: wkp] = s existentialBase[keyPath: rkp] = s existentialBase[keyPath: pkp] = s // expected-error{{}} } struct AA { subscript(x: Int) -> Int { return x } subscript(labeled x: Int) -> Int { return x } var c: CC? = CC() } class CC { var i = 0 } func testKeyPathOptional() { _ = \AA.c?.i _ = \AA.c!.i // SR-6198 let path: KeyPath! = \CC.i let cc = CC() _ = cc[keyPath: path] } func testLiteralInAnyContext() { let _: AnyKeyPath = \A.property let _: AnyObject = \A.property let _: Any = \A.property let _: Any? = \A.property } func testMoreGeneralContext(_: KeyPath, with: T.Type) {} func testLiteralInMoreGeneralContext() { testMoreGeneralContext(\.property, with: A.self) } func testLabeledSubscript() { let _: KeyPath = \AA.[labeled: 0] let _: KeyPath = \.[labeled: 0] let k = \AA.[labeled: 0] // TODO: These ought to work without errors. let _ = \AA.[keyPath: k] // expected-error{{}} let _ = \AA.[keyPath: \AA.[labeled: 0]] // expected-error{{}} } func testInvalidKeyPathComponents() { let _ = \.{return 0} // expected-error* {{}} } class X { class var a: Int { return 1 } static var b = 2 } func testStaticKeyPathComponent() { _ = \X.a // expected-error{{}} _ = \X.Type.a // expected-error{{cannot refer to static member}} _ = \X.b // expected-error{{}} _ = \X.Type.b // expected-error{{cannot refer to static member}} } class Bass: Hashable { static func ==(_: Bass, _: Bass) -> Bool { return false } var hashValue: Int { return 0 } } class Treble: Bass { } struct BassSubscript { subscript(_: Bass) -> Int { fatalError() } subscript(_: @autoclosure () -> String) -> Int { fatalError() } } func testImplicitConversionInSubscriptIndex() { _ = \BassSubscript.[Treble()] _ = \BassSubscript.["hello"] // expected-error{{must be Hashable}} } // SR-6106 func sr6106() { class B {} class A { var b: B? = nil } class C { var a: A? func myFunc() { let _ = \C.a?.b } } } func testSyntaxErrors() { // expected-note{{}} _ = \. ; // expected-error{{expected member name following '.'}} _ = \.a ; _ = \[a ; _ = \[a]; _ = \? ; _ = \! ; _ = \. ; // expected-error{{expected member name following '.'}} _ = \.a ; _ = \[a ; _ = \[a,; _ = \[a:; _ = \[a]; _ = \.a?; _ = \.a!; _ = \A ; _ = \A, ; _ = \A< ; _ = \A. ; // expected-error{{expected member name following '.'}} _ = \A.a ; _ = \A[a ; _ = \A[a]; _ = \A? ; _ = \A! ; _ = \A. ; // expected-error{{expected member name following '.'}} _ = \A.a ; _ = \A[a ; _ = \A[a,; _ = \A[a:; _ = \A[a]; _ = \A.a?; _ = \A.a!; } // expected-error@+1{{}}