Files
swift-mirror/test/expr/unary/keypath/keypath.swift
2025-03-19 10:54:09 -07:00

1430 lines
54 KiB
Swift

// RUN: %target-swift-frontend -enable-experimental-feature KeyPathWithMethodMembers -typecheck -parse-as-library %s -verify
// REQUIRES: swift_feature_KeyPathWithMethodMembers
struct Sub: Hashable {
static func ==(_: Sub, _: Sub) -> Bool { return true }
func hash(into hasher: inout Hasher) {}
}
struct OptSub: Hashable {
static func ==(_: OptSub, _: OptSub) -> Bool { return true }
func hash(into hasher: inout Hasher) {}
}
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 { } }
func foo(_ b: NonHashableSub) {}
static func foo(_ b: Sub) {}
static func ==(_: A, _: A) -> Bool { fatalError() }
func hash(into hasher: inout Hasher) { fatalError() }
}
struct B {}
struct C<T> { // expected-note 4 {{'T' declared as parameter to type 'C'}}
var value: T
subscript() -> T { get { return value } }
subscript(sub: Sub) -> T { get { return value } set { } }
subscript<U: Hashable>(sub: U) -> U { get { return sub } set { } }
subscript<X>(noHashableConstraint sub: X) -> X { get { return sub } set { } }
}
struct Unavailable {
@available(*, unavailable)
var unavailableProperty: Int { 0 }
// expected-note@-1 {{'unavailableProperty' has been explicitly marked unavailable here}}
@available(*, unavailable)
subscript(x: Sub) -> Int { get { } set { } }
// expected-note@-1 {{'subscript(_:)' has been explicitly marked unavailable here}}
}
struct Deprecated {
@available(*, deprecated)
var deprecatedProperty: Int
@available(*, deprecated)
subscript(x: Sub) -> Int { get { } set { } }
}
@available(*, deprecated)
func getDeprecatedSub() -> Sub {
return Sub()
}
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<T> {}
func expect<T>(_ x: inout T, toHaveType _: Exactly<T>.Type) {}
func testKeyPath(sub: Sub, optSub: OptSub,
nonHashableSub: NonHashableSub, x: Int) {
var a = \A.property
expect(&a, toHaveType: Exactly<WritableKeyPath<A, Prop>>.self)
var b = \A.[sub]
expect(&b, toHaveType: Exactly<WritableKeyPath<A, A>>.self)
var c = \A.[sub].property
expect(&c, toHaveType: Exactly<WritableKeyPath<A, Prop>>.self)
var d = \A.optProperty?
expect(&d, toHaveType: Exactly<KeyPath<A, Prop?>>.self)
var e = \A.optProperty?[sub]
expect(&e, toHaveType: Exactly<KeyPath<A, A?>>.self)
var f = \A.optProperty!
expect(&f, toHaveType: Exactly<WritableKeyPath<A, Prop>>.self)
var g = \A.property[optSub]?.optProperty![sub]
expect(&g, toHaveType: Exactly<KeyPath<A, A?>>.self)
var h = \[A].property
expect(&h, toHaveType: Exactly<KeyPath<[A], Prop>>.self)
var i = \[A].property.nonMutatingProperty
expect(&i, toHaveType: Exactly<ReferenceWritableKeyPath<[A], B>>.self)
var j = \[A].[x]
expect(&j, toHaveType: Exactly<WritableKeyPath<[A], A>>.self)
var k = \[A: B].[A()]
expect(&k, toHaveType: Exactly<WritableKeyPath<[A: B], B?>>.self)
var l = \C<A>.value
expect(&l, toHaveType: Exactly<WritableKeyPath<C<A>, A>>.self)
var hashableCapture = \A.Type.foo(Sub())
expect(&hashableCapture, toHaveType: Exactly<WritableKeyPath<A.Type, ()>>.self)
// expected-error@+1 {{method argument of type 'NonHashableSub' in a key path must be Hashable}}
_ = \A.foo(NonHashableSub())
// expected-error@+1{{generic parameter 'T' could not be inferred}}
_ = \C.value
// expected-error@+1{{}}
_ = \(() -> ()).noMember
let _: (A) -> Prop = \.property
let _: (A) -> Prop? = \.property
let _: PartialKeyPath<A> = \.property
let _: KeyPath<A, Prop> = \.property
let _: WritableKeyPath<A, Prop> = \.property
let _: ReferenceWritableKeyPath<A, Prop> = \.property
//expected-error@-1 {{cannot convert key path type 'WritableKeyPath<A, Prop>' to contextual type 'ReferenceWritableKeyPath<A, Prop>'}}
let _: (A) -> A? = \.[sub]
let _: (A) -> A = \.[sub]
let _: PartialKeyPath<A> = \.[sub]
let _: KeyPath<A, A> = \.[sub]
let _: WritableKeyPath<A, A> = \.[sub]
let _: ReferenceWritableKeyPath<A, A> = \.[sub]
//expected-error@-1 {{cannot convert key path type 'WritableKeyPath<A, A>' to contextual type 'ReferenceWritableKeyPath<A, A>'}}
let _: (A) -> Prop?? = \.optProperty?
let _: (A) -> Prop? = \.optProperty?
let _: PartialKeyPath<A> = \.optProperty?
let _: KeyPath<A, Prop?> = \.optProperty?
// expected-error@+1{{cannot convert}}
let _: WritableKeyPath<A, Prop?> = \.optProperty?
// expected-error@+1{{cannot convert}}
let _: ReferenceWritableKeyPath<A, Prop?> = \.optProperty?
let _: (A) -> A?? = \.optProperty?[sub]
let _: (A) -> A? = \.optProperty?[sub]
let _: PartialKeyPath<A> = \.optProperty?[sub]
let _: KeyPath<A, A?> = \.optProperty?[sub]
// expected-error@+1{{cannot convert}}
let _: WritableKeyPath<A, A?> = \.optProperty?[sub]
// expected-error@+1{{cannot convert}}
let _: ReferenceWritableKeyPath<A, A?> = \.optProperty?[sub]
let _: KeyPath<A, Prop> = \.optProperty!
let _: KeyPath<A, Prop> = \.optLetProperty!
let _: KeyPath<A, Prop?> = \.property[optSub]?.optProperty!
let _: KeyPath<A, A?> = \.property[optSub]?.optProperty![sub]
let _: (C<A>) -> A? = \.value
let _: (C<A>) -> A = \.value
let _: PartialKeyPath<C<A>> = \.value
let _: KeyPath<C<A>, A> = \.value
let _: WritableKeyPath<C<A>, A> = \.value
let _: ReferenceWritableKeyPath<C<A>, A> = \.value
// expected-error@-1 {{cannot convert key path type 'WritableKeyPath<C<A>, A>' to contextual type 'ReferenceWritableKeyPath<C<A>, A>'}}
let _: (C<A>) -> A? = \C.value
let _: (C<A>) -> A = \C.value
let _: PartialKeyPath<C<A>> = \C.value
let _: KeyPath<C<A>, A> = \C.value
let _: WritableKeyPath<C<A>, A> = \C.value
// expected-error@+1{{cannot convert}}
let _: ReferenceWritableKeyPath<C<A>, A> = \C.value
let _: (Prop) -> B? = \.nonMutatingProperty
let _: (Prop) -> B = \.nonMutatingProperty
let _: PartialKeyPath<Prop> = \.nonMutatingProperty
let _: KeyPath<Prop, B> = \.nonMutatingProperty
let _: WritableKeyPath<Prop, B> = \.nonMutatingProperty
let _: ReferenceWritableKeyPath<Prop, B> = \.nonMutatingProperty
var m = [\A.property, \A.[sub], \A.optProperty!]
expect(&m, toHaveType: Exactly<[PartialKeyPath<A>]>.self)
// \.optProperty returns an optional of Prop and `\.[sub]` returns `A`, all this unifies into `[PartialKeyPath<A>]`
var n = [\A.property, \.optProperty, \.[sub], \.optProperty!]
expect(&n, toHaveType: Exactly<[PartialKeyPath<A>]>.self)
let _: [PartialKeyPath<A>] = [\.property, \.optProperty, \.[sub], \.optProperty!]
var o = [\A.property, \C<A>.value]
expect(&o, toHaveType: Exactly<[AnyKeyPath]>.self)
let _: AnyKeyPath = \A.property
let _: AnyKeyPath = \C<A>.value
let _: AnyKeyPath = \.property // expected-error {{'AnyKeyPath' does not provide enough context for root type to be inferred; consider explicitly specifying a root type}} {{24-24=<#Root#>}}
let _: AnyKeyPath = \C.value // expected-error{{generic parameter 'T' could not be inferred}}
let _: AnyKeyPath = \.value // expected-error {{'AnyKeyPath' does not provide enough context for root type to be inferred; consider explicitly specifying a root type}} {{24-24=<#Root#>}}
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<Int>.[]
let _ = \C<Int>.[sub]
let _ = \C<Int>.[noHashableConstraint: sub]
let _ = \C<Int>.[noHashableConstraint: nonHashableSub] // expected-error{{subscript index of type 'NonHashableSub' in a key path must be Hashable}}
let _ = \Unavailable.unavailableProperty // expected-error {{'unavailableProperty' is unavailable}}
let _ = \Unavailable.[sub] // expected-error {{'subscript(_:)' is unavailable}}
let _ = \Deprecated.deprecatedProperty // expected-warning {{'deprecatedProperty' is deprecated}}
let _ = \Deprecated.[sub] // expected-warning {{'subscript(_:)' is deprecated}}
let _ = \A.[getDeprecatedSub()] // expected-warning {{'getDeprecatedSub()' is deprecated}}
}
func testKeyPathInGenericContext<H: Hashable, X>(hashable: H, anything: X) {
let _ = \C<Int>.[hashable]
let _ = \C<Int>.[noHashableConstraint: hashable]
let _ = \C<Int>.[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 can only appear inside a string literal}}
\(x, radix: 16) // expected-error{{string interpolation can only appear inside a string literal}}
}
func testNoComponents() {
let _: KeyPath<A, A> = \A // expected-error{{must have at least one component}}
let _: KeyPath<C, A> = \C // expected-error{{must have at least one component}}
// expected-error@-1 {{generic parameter 'T' could not be inferred}}
let _: KeyPath<A, C> = \A // expected-error{{must have at least one component}}
// expected-error@-1 {{generic parameter 'T' could not be inferred}}
_ = \A // expected-error {{key path must have at least one component}}
}
struct TupleStruct {
var unlabeled: (Int, String)
var labeled: (foo: Int, bar: String)
}
typealias UnlabeledGenericTuple<T, U> = (T, U)
typealias LabeledGenericTuple<T, U> = (a: T, b: U)
func tupleComponent<T, U>(_: T, _: U) {
let _ = \(Int, String).0
let _ = \(Int, String).1
let _ = \TupleStruct.unlabeled.0
let _ = \TupleStruct.unlabeled.1
let _ = \(foo: Int, bar: String).0
let _ = \(foo: Int, bar: String).1
let _ = \(foo: Int, bar: String).foo
let _ = \(foo: Int, bar: String).bar
let _ = \TupleStruct.labeled.0
let _ = \TupleStruct.labeled.1
let _ = \TupleStruct.labeled.foo
let _ = \TupleStruct.labeled.bar
let _ = \(T, U).0
let _ = \(T, U).1
let _ = \UnlabeledGenericTuple<T, U>.0
let _ = \UnlabeledGenericTuple<T, U>.1
let _ = \(a: T, b: U).0
let _ = \(a: T, b: U).1
let _ = \(a: T, b: U).a
let _ = \(a: T, b: U).b
let _ = \LabeledGenericTuple<T, U>.0
let _ = \LabeledGenericTuple<T, U>.1
let _ = \LabeledGenericTuple<T, U>.a
let _ = \LabeledGenericTuple<T, U>.b
}
func tuple_el_0<T, U>() -> KeyPath<(T, U), T> {
return \.0
}
func tuple_el_1<T, U>() -> KeyPath<(T, U), U> {
return \.1
}
func tupleGeneric<T, U>(_ v: (T, U)) {
_ = (1, "hello")[keyPath: tuple_el_0()]
_ = (1, "hello")[keyPath: tuple_el_1()]
_ = v[keyPath: tuple_el_0()]
_ = v[keyPath: tuple_el_1()]
_ = ("tuple", "too", "big")[keyPath: tuple_el_1()]
// expected-note@-12 {{}}
// expected-error@-2 {{generic parameter 'T' could not be inferred}}
// expected-error@-3 {{generic parameter 'U' could not be inferred}}
}
struct Z { }
func testKeyPathSubscript(readonly: Z, writable: inout Z,
kp: KeyPath<Z, Int>,
wkp: WritableKeyPath<Z, Int>,
rkp: ReferenceWritableKeyPath<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 through subscript: 'kp' is a read-only key path}}
writable[keyPath: kp] = sink // expected-error{{cannot assign through subscript: 'kp' is a read-only key path}}
readonly[keyPath: wkp] = sink // expected-error{{cannot assign through subscript: 'readonly' is a 'let' constant}}
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<Any>.self)
var anySink2 = writable[keyPath: pkp]
expect(&anySink2, toHaveType: Exactly<Any>.self)
readonly[keyPath: pkp] = anySink1 // expected-error{{cannot assign through subscript: 'pkp' is a read-only key path}}
writable[keyPath: pkp] = anySink2 // expected-error{{cannot assign through subscript: 'pkp' is a read-only key path}}
let akp: AnyKeyPath = pkp
var anyqSink1 = readonly[keyPath: akp]
expect(&anyqSink1, toHaveType: Exactly<Any?>.self)
var anyqSink2 = writable[keyPath: akp]
expect(&anyqSink2, toHaveType: Exactly<Any?>.self)
readonly[keyPath: akp] = anyqSink1 // expected-error{{cannot assign through subscript: 'readonly' is a 'let' constant}}
writable[keyPath: akp] = anyqSink2 // expected-error{{cannot assign through subscript: 'writable' is immutable}}
}
struct ZwithSubscript {
subscript(keyPath kp: KeyPath<ZwithSubscript, Int>) -> Int { return 0 }
subscript(keyPath kp: WritableKeyPath<ZwithSubscript, Int>) -> Int { return 0 }
subscript(keyPath kp: ReferenceWritableKeyPath<ZwithSubscript, Int>) -> Int { return 0 }
subscript(keyPath kp: PartialKeyPath<ZwithSubscript>) -> Any { return 0 }
}
struct NotZ {}
func testKeyPathSubscript(readonly: ZwithSubscript, writable: inout ZwithSubscript,
wrongType: inout NotZ,
kp: KeyPath<ZwithSubscript, Int>,
wkp: WritableKeyPath<ZwithSubscript, Int>,
rkp: ReferenceWritableKeyPath<ZwithSubscript, 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 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<Any>.self)
var anySink2 = writable[keyPath: pkp]
expect(&anySink2, toHaveType: Exactly<Any>.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<Any?>.self)
var anyqSink2 = writable[keyPath: akp]
expect(&anyqSink2, toHaveType: Exactly<Any?>.self)
// FIXME: silently falls back to keypath application, which seems inconsistent
readonly[keyPath: akp] = anyqSink1 // expected-error{{cannot assign through subscript: 'readonly' is a 'let' constant}}
// FIXME: silently falls back to keypath application, which seems inconsistent
writable[keyPath: akp] = anyqSink2 // expected-error{{cannot assign through subscript: 'writable' is 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<Z.Type, Int>,
wkp: WritableKeyPath<Z.Type, Int>,
rkp: ReferenceWritableKeyPath<Z.Type, 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 through subscript: 'kp' is a read-only key path}}
writable[keyPath: kp] = sink // expected-error{{cannot assign through subscript: 'kp' is a read-only key path}}
readonly[keyPath: wkp] = sink // expected-error{{cannot assign through subscript: 'readonly' is a 'let' constant}}
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 through subscript: 'kp' is a read-only key path}}
writable[keyPath: kp] = sink // expected-error{{cannot assign through subscript: 'kp' is a read-only key path}}
readonly[keyPath: wkp] = sink // expected-error{{cannot assign through subscript: 'readonly' is a 'let' constant}}
writable[keyPath: wkp] = sink
readonly[keyPath: rkp] = sink
writable[keyPath: rkp] = sink
}
func testKeyPathSubscriptLValue(base: Z, kp: inout KeyPath<Z, Z>) {
_ = base[keyPath: kp]
}
func testKeyPathSubscriptExistentialBase(concreteBase: inout B,
existentialBase: inout P,
kp: KeyPath<P, String>,
wkp: WritableKeyPath<P, String>,
rkp: ReferenceWritableKeyPath<P, String>,
pkp: PartialKeyPath<P>,
s: String) {
_ = concreteBase[keyPath: kp]
_ = concreteBase[keyPath: wkp]
_ = concreteBase[keyPath: rkp]
_ = concreteBase[keyPath: pkp]
concreteBase[keyPath: kp] = s // expected-error {{cannot assign through subscript: 'kp' is a read-only key path}}
concreteBase[keyPath: wkp] = s // expected-error {{key path with root type 'any P' cannot be applied to a base of type 'B'}}
concreteBase[keyPath: rkp] = s
concreteBase[keyPath: pkp] = s // expected-error {{cannot assign through subscript: 'pkp' is a read-only key path}}
_ = existentialBase[keyPath: kp]
_ = existentialBase[keyPath: wkp]
_ = existentialBase[keyPath: rkp]
_ = existentialBase[keyPath: pkp]
existentialBase[keyPath: kp] = s // expected-error {{cannot assign through subscript: 'kp' is a read-only key path}}
existentialBase[keyPath: wkp] = s
existentialBase[keyPath: rkp] = s
existentialBase[keyPath: pkp] = s // expected-error {{cannot assign through subscript: 'pkp' is a read-only key path}}
}
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
_ = \AA.c?.i.hashValue
// https://github.com/apple/swift/issues/48750
let path: KeyPath<CC,Int>! = \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<T, U>(_: KeyPath<T, U>, with: T.Type) {}
func testLiteralInMoreGeneralContext() {
testMoreGeneralContext(\.property, with: A.self)
}
func testLabeledSubscript() {
let _: KeyPath<AA, Int> = \AA.[labeled: 0]
let _: KeyPath<AA, Int> = \.[labeled: 0]
let k = \AA.[labeled: 0]
// TODO: These ought to work without errors.
let _ = \AA.[keyPath: k]
// expected-error@-1 {{cannot convert value of type 'KeyPath<AA, Int>' to expected argument type 'Int'}}
// expected-error@-2 {{extraneous argument label 'keyPath:' in call}}
let _ = \AA.[keyPath: \AA.[labeled: 0]] // expected-error {{extraneous argument label 'keyPath:' in call}}
// expected-error@-1 {{cannot convert value of type 'KeyPath<AA, Int>' to expected argument type 'Int'}}
}
func testInvalidKeyPathComponents() {
let _ = \.{return 0} // expected-error* {{}}
}
struct W {
static let h = 50
}
class X {
class var a: Int { return 1 }
static var b = 20
let c = true
static subscript(d: Int) -> String { "\(d)" }
var e: W.Type? { return W.self }
}
class Y : X {
subscript(f: Int) -> W.Type { W.self }
static subscript(g: Int) -> W.Type { W.self }
}
func testStaticKeyPathComponent() {
_ = \X.a // expected-error{{static member 'a' cannot be used on instance of type 'X'}}
_ = \X.Type.a
_ = \X.b // expected-error{{static member 'b' cannot be used on instance of type 'X'}}
_ = \X.Type.b
_ = \X.c
_ = \X.Type.c // expected-error{{instance member 'c' cannot be used on type 'X'}}
_ = \X.[42] // expected-error{{static member 'subscript(_:)' cannot be used on instance of type 'X'}}
_ = \X.Type.[42]
let _: KeyPath<X, Int?> = \.e?.h
let _: PartialKeyPath<X> = \.e?.h
let _: AnyKeyPath = \X.e?.h
let _ : KeyPath<Y, W.Type> = \Y.[40]
let _ : KeyPath<Y.Type, W.Type> = \Y.Type.[70]
}
class Bass: Hashable {
static func ==(_: Bass, _: Bass) -> Bool { return false }
func hash(into hasher: inout Hasher) {}
}
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}}
}
// Crash in diagnostics + https://github.com/apple/swift/issues/53839
struct UnambiguousSubscript {
subscript(sub: Sub) -> Int { get { } set { } }
subscript(y y: Sub) -> Int { get { } set { } }
}
func useUnambiguousSubscript(_ sub: Sub) {
let _: PartialKeyPath<UnambiguousSubscript> = \.[sub]
}
struct BothUnavailableSubscript {
@available(*, unavailable)
subscript(sub: Sub) -> Int { get { } set { } } // expected-note {{'subscript(_:)' has been explicitly marked unavailable here}}
@available(*, unavailable)
subscript(y y: Sub) -> Int { get { } set { } }
}
func useBothUnavailableSubscript(_ sub: Sub) {
let _: PartialKeyPath<BothUnavailableSubscript> = \.[sub]
// expected-error@-1 {{'subscript(_:)' is unavailable}}
}
// https://github.com/apple/swift/issues/48661
func f_48661() {
class B {}
class A {
var b: B? = nil
}
class C {
var a: A?
func myFunc() {
let _ = \C.a?.b
}
}
}
// https://github.com/apple/swift/issues/49293
func f_49293() {
struct ABC {
let value: Int
func value(adding i: Int) -> Int { return value + i }
}
let abc = ABC(value: 0)
func get<T>(for kp: KeyPath<ABC, T>) -> T {
return abc[keyPath: kp]
}
_ = get(for: \.value)
}
// https://github.com/apple/swift/issues/49928
func f_49928() {
_ = ""[keyPath: \.count]
_ = ""[keyPath: \String.count]
let arr1 = [1]
_ = arr1[keyPath: \.[0]]
_ = arr1[keyPath: \[Int].[0]]
let dic1 = [1:"s"]
_ = dic1[keyPath: \.[1]]
_ = dic1[keyPath: \[Int: String].[1]]
var arr2 = [1]
arr2[keyPath: \.[0]] = 2
arr2[keyPath: \[Int].[0]] = 2
var dic2 = [1:"s"]
dic2[keyPath: \.[1]] = ""
dic2[keyPath: \[Int: String].[1]] = ""
_ = [""][keyPath: \.[0]]
_ = [""][keyPath: \[String].[0]]
_ = ["": ""][keyPath: \.["foo"]]
_ = ["": ""][keyPath: \[String: String].["foo"]]
class A {
var a: String = ""
}
_ = A()[keyPath: \.a]
_ = A()[keyPath: \A.a]
A()[keyPath: \.a] = ""
A()[keyPath: \A.a] = ""
}
struct VisibilityTesting {
private(set) var x: Int
fileprivate(set) var y: Int
let z: Int
// Key path exprs should not get special dispensation to write to lets
// in init contexts
init() {
var xRef = \VisibilityTesting.x
var yRef = \VisibilityTesting.y
var zRef = \VisibilityTesting.z
expect(&xRef,
toHaveType: Exactly<WritableKeyPath<VisibilityTesting, Int>>.self)
expect(&yRef,
toHaveType: Exactly<WritableKeyPath<VisibilityTesting, Int>>.self)
// Allow WritableKeyPath for Swift 3/4 only.
expect(&zRef,
toHaveType: Exactly<WritableKeyPath<VisibilityTesting, Int>>.self)
}
func inPrivateContext() {
var xRef = \VisibilityTesting.x
var yRef = \VisibilityTesting.y
var zRef = \VisibilityTesting.z
expect(&xRef,
toHaveType: Exactly<WritableKeyPath<VisibilityTesting, Int>>.self)
expect(&yRef,
toHaveType: Exactly<WritableKeyPath<VisibilityTesting, Int>>.self)
expect(&zRef,
toHaveType: Exactly<KeyPath<VisibilityTesting, Int>>.self)
}
}
struct VisibilityTesting2 {
func inFilePrivateContext() {
var xRef = \VisibilityTesting.x
var yRef = \VisibilityTesting.y
var zRef = \VisibilityTesting.z
// Allow WritableKeyPath for Swift 3/4 only.
expect(&xRef,
toHaveType: Exactly<WritableKeyPath<VisibilityTesting, Int>>.self)
expect(&yRef,
toHaveType: Exactly<WritableKeyPath<VisibilityTesting, Int>>.self)
expect(&zRef,
toHaveType: Exactly<KeyPath<VisibilityTesting, Int>>.self)
}
}
protocol PP {}
class Base : PP { var i: Int = 0 }
class Derived : Base {}
func testSubtypeKeypathClass(_ keyPath: ReferenceWritableKeyPath<Base, Int>) {
testSubtypeKeypathClass(\Derived.i)
}
func testSubtypeKeypathProtocol(_ keyPath: ReferenceWritableKeyPath<PP, Int>) {
testSubtypeKeypathProtocol(\Base.i)
// expected-error@-1 {{cannot convert value of type 'ReferenceWritableKeyPath<Base, Int>' to expected argument type 'ReferenceWritableKeyPath<any PP, Int>'}}
// expected-note@-2 {{arguments to generic parameter 'Root' ('Base' and 'any PP') are expected to be equal}}
}
// rdar://problem/32057712
struct Container {
let base: Base? = Base()
}
var rdar32057712 = \Container.base?.i
var identity1 = \Container.self
var identity2: WritableKeyPath = \Container.self
var identity3: WritableKeyPath<Container, Container> = \Container.self
var identity4: WritableKeyPath<Container, Container> = \.self
var identity5: KeyPath = \Container.self
var identity6: KeyPath<Container, Container> = \Container.self
var identity7: KeyPath<Container, Container> = \.self
var identity8: PartialKeyPath = \Container.self
var identity9: PartialKeyPath<Container> = \Container.self
var identity10: PartialKeyPath<Container> = \.self
var identity11: AnyKeyPath = \Container.self
var identity12: (Container) -> Container = \Container.self
var identity13: (Container) -> Container = \.self
var identity14: (Container) -> Container? = \Container.self
var identity15: (Container) -> Container? = \.self
var interleavedIdentityComponents = \Container.self.base.self?.self.i.self
protocol P_With_Static_Members {
static var x: Int { get }
static var arr: [Int] { get }
}
func test_keypath_with_static_members(_ p: P_With_Static_Members) {
let _ = p[keyPath: \.x]
// expected-error@-1 {{static member 'x' cannot be used on instance of type 'any P_With_Static_Members'}}
let _: KeyPath<P_With_Static_Members, Int> = \.x
// expected-error@-1 {{static member 'x' cannot be used on instance of type 'any P_With_Static_Members'}}
let _ = \P_With_Static_Members.arr.count
// expected-error@-1 {{static member 'arr' cannot be used on instance of type 'any P_With_Static_Members'}}
let _ = p[keyPath: \.arr.count]
// expected-error@-1 {{static member 'arr' cannot be used on instance of type 'any P_With_Static_Members'}}
struct S {
static var foo: String = "Hello"
var bar: Bar
}
struct Bar {
static var baz: Int = 42
}
func foo(_ s: S) {
let _ = \S.Type.foo
let _ = s[keyPath: \.foo]
// expected-error@-1 {{static member 'foo' cannot be used on instance of type 'S'}}
let _: KeyPath<S, String> = \.foo
// expected-error@-1 {{static member 'foo' cannot be used on instance of type 'S'}}
let _ = \S.foo
// expected-error@-1 {{static member 'foo' cannot be used on instance of type 'S'}}
let _ = \S.bar.baz
// expected-error@-1 {{static member 'baz' cannot be used on instance of type 'Bar'}}
let _ = s[keyPath: \.bar.baz]
// expected-error@-1 {{static member 'baz' cannot be used on instance of type 'Bar'}}
}
}
func test_keypath_with_mutating_getter() {
struct S {
var foo: Int {
mutating get { return 42 }
}
subscript(_: Int) -> [Int] {
mutating get { return [] }
}
}
_ = \S.foo
// expected-error@-1 {{key path cannot refer to 'foo', which has a mutating getter}}
let _: KeyPath<S, Int> = \.foo
// expected-error@-1 {{key path cannot refer to 'foo', which has a mutating getter}}
_ = \S.[0]
// expected-error@-1 {{key path cannot refer to 'subscript(_:)', which has a mutating getter}}
_ = \S.[0].count
// expected-error@-1 {{key path cannot refer to 'subscript(_:)', which has a mutating getter}}
func test_via_subscript(_ s: S) {
_ = s[keyPath: \.foo]
// expected-error@-1 {{key path cannot refer to 'foo', which has a mutating getter}}
_ = s[keyPath: \.[0].count]
// expected-error@-1 {{key path cannot refer to 'subscript(_:)', which has a mutating getter}}
}
}
func test_keypath_with_method_refs() {
enum ValidationError: Error {
case invalidYear
}
struct S {
static let millenium = 3
var year = 2024
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 { return year + 1 }
consuming func consume() { print(year) }
func validateYear() throws {
if year < 0 { throw ValidationError.invalidYear }
}
func doubleValue(_ value: inout Int) { value *= 2 }
mutating func updateYear(to newYear: Int) { self.year = newYear }
func calculateFutureYear(after seconds: UInt64) async -> Int {
try? await Task.sleep(nanoseconds: seconds)
return year + 10
}
func validateAndCalculateFutureYear(after seconds: UInt64) async throws -> Int {
try validateYear()
try await Task.sleep(nanoseconds: seconds)
return year + 10
}
subscript(index: Int) -> Int { return year + index }
}
let _: KeyPath<S, (Int, Int) -> Int> = \.add
let _: KeyPath<S, (Int, Int) -> Int> = \.add()
// expected-error@-1 {{cannot assign value of type 'KeyPath<S, Int>' to type 'KeyPath<S, (Int, Int) -> Int>'}}
// expected-note@-2 {{arguments to generic parameter 'Value' ('Int' and '(Int, Int) -> Int') are expected to be equal}}
let _: KeyPath<S, Int> = \.add() // expected-error {{type of expression is ambiguous without a type annotation}}
let _: KeyPath<S, (Int) -> Int> = \.add(this:)
let _: KeyPath<S, Int> = \.add(that: 1)
let _: KeyPath<S, (Int) -> Int> = \.subtract // expected-error {{static member 'subtract' cannot be used on instance of type 'S'}}
let _ = \S.Type.subtract(1)
let _: KeyPath<S, () -> Int> = \S.nonisolatedNextYear
let _: KeyPath<S, Int> = \S.nonisolatedNextYear()
do {
try S()[keyPath: \S.validateYear]() // expected-error {{cannot form key path to instance method with 'throws' or 'async'}}
} catch {
print("Validation failed: \(error)")
}
var value = 2025
let _ = \S.doubleValue(&value) // expected-error {{cannot pass an inout argument to a keypath method}}
let _: KeyPath<S, ()> = \S.updateYear(to: 2025) // expected-error {{key path cannot refer to mutating method 'updateYear(to:)}}
let _: KeyPath<S, Int> = \S.calculateFutureYear(after: 5) // expected-error {{cannot form key path to instance method with 'throws' or 'async'}}
let _: KeyPath<S, Int> = \S.validateAndCalculateFutureYear(after: 5) // expected-error {{cannot form key path to instance method with 'throws' or 'async'}}
let _: KeyPath<S, () -> S> = \.init // expected-error {{static member 'init()' cannot be used on instance of type 'S'}}
let _: KeyPath<S, (Int) -> S> = \.init(val:) // expected-error {{static member 'init(val:)' cannot be used on instance of type 'S'}}
let _: KeyPath<S, S> = \.init(val: 2025) // expected-error {{static member 'init(val:)' cannot be used on instance of type 'S'}}
let _: KeyPath<S.Type, () -> S> = \S.Type.init
let _: KeyPath<S.Type, (Int) -> S> = \S.Type.init(val:)
let _: KeyPath<S.Type, S> = \S.Type.init(val: 2025)
let _: KeyPath<S.Type, Int> = \.init(val:2025).year
let _ = \S.Type.init(val: 2025).nonisolatedNextYear()
let _ = \S.Type.init()[0]
let _ = \S.Type.init(val: 2025).nonisolatedNextYear().signum()
let _ = \S.Type.init(val: 2025).nonisolatedNextYear().description
let _: KeyPath<S, ()> = \S.consume()
let _: AnyKeyPath = \S.add(this:)
let _: PartialKeyPath = \S.add
class E: Hashable {
static func == (lhs: E, rhs: E) -> Bool { return lhs === rhs }
func hash(into hasher: inout Hasher) { hasher.combine(ObjectIdentifier(self)) }
private var storedClosure: (() -> Void)?
func saveClosure(_ closure: @escaping () -> Void) { storedClosure = closure }
}
class NonhashableE {}
struct BaseType {
func foo(_ e: E) {}
func foo(_ e: NonhashableE) {}
}
let hashableInstance = E()
let nonhashableInstance = NonhashableE()
let _ = \BaseType.foo(hashableInstance)
let _ = \BaseType.foo(nonhashableInstance) // expected-error {{method argument of type 'NonhashableE' in a key path must be Hashable}}
struct A {
func foo() -> B { return B() }
static func faz() -> B { return B() }
}
struct B {
var bar: Int = 42
func baz() -> Int { return 42 }
subscript(index: Int) -> Int { return index }
}
let _: KeyPath<A, Int> = \.foo.bar // expected-error {{type of expression is ambiguous without a type annotation}}
let _: KeyPath<A, Int> = \.faz.bar // expected-error {{static member 'faz()' cannot be used on instance of type 'A'}}
let _ = \A.foo.bar // expected-error {{type of expression is ambiguous without a type annotation}}
let _ = \A.Type.faz.bar // expected-error {{type of expression is ambiguous without a type annotation}}
let _: KeyPath<A, Int> = \.foo().bar
let _: KeyPath<A.Type, Int> = \.faz().bar
let _ = \A.foo().bar
let _ = \A.Type.faz().bar
let _: KeyPath<A.Type, Int> = \.faz().bar
let _: KeyPath<A, Int> = \.foo().baz()
let _: KeyPath<A, Int> = \.foo().baz()
let _: KeyPath<A.Type, Int> = \A.Type.faz()[0]
}
// https://github.com/apple/swift/issues/54961
protocol Zonk {
func wargle()
}
typealias Blatz = (gloop: String, zoop: Zonk?)
func f_54961(fleep: [Blatz]) {
let _ = fleep.compactMap(\.zoop?.wargle)
}
// https://github.com/apple/swift/issues/52867
// Argument type 'KeyPath<String, Int>' does not conform to expected type 'Any'
func test_keypath_in_any_context() {
func foo(_: Any) {}
foo(\String.count) // Ok
}
protocol PWithTypeAlias {
typealias Key = WritableKeyPath<Self, Int?>
static var fooKey: Key? { get }
static var barKey: Key! { get }
static var fazKey: Key?? { get }
static var bazKey: Key?! { get }
}
func test_keypath_inference_with_optionals() {
final class S : PWithTypeAlias {
static var fooKey: Key? { return \.foo }
static var barKey: Key! { return \.foo }
static var fazKey: Key?? { return \.foo }
static var bazKey: Key?! { return \.foo }
var foo: Int? = nil
}
}
// https://github.com/apple/swift/issues/53967
func f_53967() {
struct S1 {
subscript(x x: Int) -> Int { x }
}
_ = \S1.[5] // expected-error {{missing argument label 'x:' in call}} {{12-12=x: }}
struct S2 {
subscript(x x: Int) -> Int { x } // expected-note {{incorrect labels for candidate (have: '(_:)', expected: '(x:)')}}
subscript(y y: Int) -> Int { y } // expected-note {{incorrect labels for candidate (have: '(_:)', expected: '(y:)')}}
}
_ = \S2.[5] // expected-error {{no exact matches in call to subscript}}
struct S3 {
subscript(x x: Int, y y: Int) -> Int { x }
}
_ = \S3.[y: 5, x: 5] // expected-error {{argument 'x' must precede argument 'y'}}
struct S4 {
subscript(x: (Int, Int)) -> Int { x.0 }
}
_ = \S4.[1, 4] // expected-error {{subscript expects a single parameter of type '(Int, Int)'}} {{12-12=(}} {{16-16=)}}
// expected-error@-1 {{subscript index of type '(Int, Int)' in a key path must be Hashable}}
}
// https://github.com/apple/swift/issues/54718
// Ban keypaths with contextual root and without a leading dot.
struct S_54718 {
let property: [Int] = []
let kp1: KeyPath<S_54718, Int> = \property.count // expected-error {{a Swift key path with contextual root must begin with a leading dot}}{{37-37=.}}
let kp2: KeyPath<S_54718, Int> = \.property.count // Ok
let kp3: KeyPath<S_54718, Int> = \S_54718.property.count // Ok
func foo1(_: KeyPath<S_54718, Int> = \property.count) {} // expected-error {{a Swift key path with contextual root must begin with a leading dot}}{{41-41=.}}
func foo2(_: KeyPath<S_54718, Int> = \.property.count) {} // Ok
func foo3(_: KeyPath<S_54718, Int> = \S_54718.property.count) {} // Ok
func foo4<T>(_: KeyPath<S_54718, T>) {}
func useFoo4() {
foo4(\property.count) // expected-error {{a Swift key path with contextual root must begin with a leading dot}}{{11-11=.}}
foo4(\.property.count) // Ok
foo4(\S_54718.property.count) // Ok
}
}
func testKeyPathHole() {
_ = \.x // expected-error {{cannot infer key path type from context; consider explicitly specifying a root type}} {{8-8=<#Root#>}}
_ = \.x.y // expected-error {{cannot infer key path type from context; consider explicitly specifying a root type}} {{8-8=<#Root#>}}
let _ : AnyKeyPath = \.x
// expected-error@-1 {{'AnyKeyPath' does not provide enough context for root type to be inferred; consider explicitly specifying a root type}} {{25-25=<#Root#>}}
let _ : AnyKeyPath = \.x.y
// expected-error@-1 {{'AnyKeyPath' does not provide enough context for root type to be inferred; consider explicitly specifying a root type}} {{25-25=<#Root#>}}
func f(_ i: Int) {}
f(\.x) // expected-error {{cannot infer key path type from context; consider explicitly specifying a root type}} {{6-6=<#Root#>}}
f(\.x.y) // expected-error {{cannot infer key path type from context; consider explicitly specifying a root type}} {{6-6=<#Root#>}}
func provideValueButNotRoot<T>(_ fn: (T) -> String) {} // expected-note 2 {{in call to function 'provideValueButNotRoot'}}
provideValueButNotRoot(\.x) // expected-error {{cannot infer key path type from context; consider explicitly specifying a root type}}
// expected-error@-1 {{generic parameter 'T' could not be inferred}}
provideValueButNotRoot(\.x.y) // expected-error {{cannot infer key path type from context; consider explicitly specifying a root type}}
// expected-error@-1 {{generic parameter 'T' could not be inferred}}
provideValueButNotRoot(\String.foo) // expected-error {{value of type 'String' has no member 'foo'}}
func provideKPValueButNotRoot<T>(_ kp: KeyPath<T, String>) {}
provideKPValueButNotRoot(\.x) // expected-error {{cannot infer key path type from context; consider explicitly specifying a root type}}
provideKPValueButNotRoot(\.x.y) // expected-error {{cannot infer key path type from context; consider explicitly specifying a root type}}
provideKPValueButNotRoot(\String.foo)
// expected-error@-1 {{value of type 'String' has no member 'foo'}}
}
func testMissingMember() {
let _: KeyPath<String, String> = \.foo // expected-error {{value of type 'String' has no member 'foo'}}
let _: KeyPath<String, String> = \.foo.bar // expected-error {{value of type 'String' has no member 'foo'}}
let _: PartialKeyPath<String> = \.foo // expected-error {{value of type 'String' has no member 'foo'}}
let _: PartialKeyPath<String> = \.foo.bar // expected-error {{value of type 'String' has no member 'foo'}}
_ = \String.x.y // expected-error {{value of type 'String' has no member 'x'}}
}
// https://github.com/apple/swift/issues/48258
func testMemberAccessOnOptionalKeyPathComponent() {
struct S1a {
var b: S1b
var b_opt: S1b?
}
struct S1b {
var m: Int
var c: S1c?
}
struct S1c {
var d: Int
}
_ = \S1a.b_opt.m
// expected-error@-1 {{value of optional type 'S1b?' must be unwrapped to refer to member 'm' of wrapped base type 'S1b'}}
// expected-note@-2 {{chain the optional using '?' to access member 'm' only for non-'nil' base values}} {{17-17=?}}
// expected-note@-3 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} {{17-17=!}}
// FIXME(diagnostics): Ideally there should be two errors here - one for `b_opt` and one for `c` but since there is
// no contextual type it means that both `!` and `?` could work to reference `.d` and that creates ambiguity which
// is not possible to diagnose at the moment.
_ = \S1a.b_opt.c.d
// expected-error@-1 {{value of optional type 'S1b?' must be unwrapped to refer to member 'c' of wrapped base type 'S1b'}}
// expected-note@-2 {{chain the optional using '?' to access member 'c' only for non-'nil' base values}} {{17-17=?}}
let _: KeyPath<S1a, Int> = \S1a.b_opt.c.d
// expected-error@-1 {{value of optional type 'S1b?' must be unwrapped to refer to member 'c' of wrapped base type 'S1b'}}
// expected-note@-2 {{chain the optional using '?' to access member 'c' only for non-'nil' base values}} {{40-40=?}}
// expected-error@-3 {{value of optional type 'S1c?' must be unwrapped to refer to member 'd' of wrapped base type 'S1c'}}
// expected-note@-4 {{chain the optional using '?' to access member 'd' only for non-'nil' base values}} {{42-42=?}}
// expected-note@-5 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} {{42-42=!}}
_ = \S1a.b_opt?.c.d
// expected-error@-1 {{value of optional type 'S1c?' must be unwrapped to refer to member 'd' of wrapped base type 'S1c'}}
// expected-note@-2 {{chain the optional using '?' to access member 'd' only for non-'nil' base values}} {{20-20=?}}
_ = \S1a.b.c.d
// expected-error@-1 {{value of optional type 'S1c?' must be unwrapped to refer to member 'd' of wrapped base type 'S1c'}}
// expected-note@-2 {{chain the optional using '?' to access member 'd' only for non-'nil' base values}} {{15-15=?}}
// expected-note@-3 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}} {{15-15=!}}
struct S2 {
subscript(_ x: Int) -> String? { get {} }
}
struct S3 {
struct Nested {
var foo = ""
}
}
\String?.count
// expected-error@-1 {{value of optional type 'String?' must be unwrapped to refer to member 'count' of wrapped base type 'String'}}
// expected-note@-2 {{use unwrapped type 'String' as key path root}} {{4-11=String}}
\Optional<String>.count
// expected-error@-1 {{value of optional type 'Optional<String>' must be unwrapped to refer to member 'count' of wrapped base type 'String'}}
// expected-note@-2 {{use unwrapped type 'String' as key path root}} {{4-20=String}}
\S2.[5].count
// expected-error@-1 {{value of optional type 'String?' must be unwrapped to refer to member 'count' of wrapped base type 'String'}}
// expected-note@-2 {{chain the optional using '?' to access member 'count' only for non-'nil' base values}}{{10-10=?}}
// expected-note@-3 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}}{{10-10=!}}
\S3.Nested?.foo.count
// expected-error@-1 {{value of optional type 'S3.Nested?' must be unwrapped to refer to member 'foo' of wrapped base type 'S3.Nested'}}
// expected-note@-2 {{use unwrapped type 'S3.Nested' as key path root}}{{4-14=S3.Nested}}
\(Int, Int)?.0
// expected-error@-1 {{value of optional type '(Int, Int)?' must be unwrapped to refer to member '0' of wrapped base type '(Int, Int)'}}
// expected-note@-2 {{use unwrapped type '(Int, Int)' as key path root}}{{4-15=(Int, Int)}}
func kp(_: KeyPath<String?, Int>) {}
kp(\.count) // expected-error {{key path root inferred as optional type 'String?' must be unwrapped to refer to member 'count' of unwrapped type 'String'}}
let _ : KeyPath<String?, Int> = \.count // expected-error {{key path root inferred as optional type 'String?' must be unwrapped to refer to member 'count' of unwrapped type 'String'}}
let _ : KeyPath<String?, Int> = \.utf8.count
// expected-error@-1 {{key path root inferred as optional type 'String?' must be unwrapped to refer to member 'utf8' of unwrapped type 'String'}}
}
func testSyntaxErrors() {
_ = \. ; // 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!;
}
// https://github.com/apple/swift/issues/56996
func f_56996() {
_ = \Int.byteSwapped.signum()
_ = \Int.byteSwapped.init() // expected-error {{static member 'init()' cannot be used on instance of type 'Int'}}
_ = \Int // expected-error {{key path must have at least one component}}
_ = \Int? // expected-error {{key path must have at least one component}}
_ = \Int. // expected-error {{invalid component of Swift key path}}
// expected-error@-1 {{expected member name following '.'}}
}
// https://github.com/apple/swift/issues/55805
// Key-path missing optional crashes compiler: Inactive constraints left over?
func f_55805() {
let _: KeyPath<String?, Int?> = \.utf8.count
// expected-error@-1 {{key path root inferred as optional type 'String?' must be unwrapped to refer to member 'utf8' of unwrapped type 'String'}}
// expected-error@-2 {{cannot assign value of type 'KeyPath<String?, Int>' to type 'KeyPath<String?, Int?>'}}
// expected-note@-3 {{arguments to generic parameter 'Value' ('Int' and 'Int?') are expected to be equal}}
}
// rdar://74711236 - crash due to incorrect member access in key path
func rdar74711236() {
struct S {
var arr: [V] = []
}
struct V : Equatable {
}
enum Type {
case store
}
struct Context {
func supported() -> [Type] {
return []
}
}
func test(context: Context?) {
var s = S()
s.arr = {
if let type = context?.store { // expected-error {{value of type 'Context' has no member 'store'}}
// `isSupported` should be an invalid declaration to trigger a crash in `map(\.option)`
let isSupported = context!.supported().contains(type)
return (isSupported ? [type] : []).map(\.option)
}
return []
}()
}
}
extension String {
var filterOut : (Self) throws -> Bool {
{ $0.contains("a") }
}
}
func test_kp_as_function_mismatch() {
let a : [String] = [ "asd", "bcd", "def" ]
let _ : (String) -> Bool = \.filterOut // expected-error{{key path value type '(String) throws -> Bool' cannot be converted to contextual type 'Bool'}}
_ = a.filter(\.filterOut) // expected-error{{key path value type '(String) throws -> Bool' cannot be converted to contextual type 'Bool'}}
let _ : (String) -> Bool = \String.filterOut // expected-error{{key path value type '(String) throws -> Bool' cannot be converted to contextual type 'Bool'}}
_ = a.filter(\String.filterOut) // expected-error{{key path value type '(String) throws -> Bool' cannot be converted to contextual type 'Bool'}}
}
func test_partial_keypath_inference() {
// rdar://problem/34144827
struct S { var i: Int = 0 }
enum E { case A(pkp: PartialKeyPath<S>) }
_ = E.A(pkp: \.i) // Ok
// rdar://problem/36472188
class ThePath {
var isWinding:Bool?
}
func walk<T>(aPath: T, forKey: PartialKeyPath<T>) {}
func walkThePath(aPath: ThePath, forKey: PartialKeyPath<ThePath>) {}
func test(path: ThePath) {
walkThePath(aPath: path, forKey: \.isWinding) // Ok
walk(aPath: path, forKey: \.isWinding) // Ok
}
}
// https://github.com/apple/swift/issues/56854
func f_56854() {
struct S1 {}
struct S2 {}
func reproduceA() -> [(S1, S2)] {
[
(true, .init(), S2.init()) // expected-error {{cannot infer contextual base in reference to member 'init'}}
]
.filter(\.0) // expected-error {{value of type 'Any' has no member '0'}}
// expected-note@-1 {{cast 'Any' to 'AnyObject' or use 'as!' to force downcast to a more specific type to access members}}
.prefix(3)
.map { ($0.1, $0.2) } // expected-error {{value of type 'Any' has no member '1'}} expected-error{{value of type 'Any' has no member '2'}}
// expected-note@-1 2 {{cast 'Any' to 'AnyObject' or use 'as!' to force downcast to a more specific type to access members}}
}
func reproduceB() -> [(S1, S2)] {
[
(true, S1.init(), .init()) // expected-error {{cannot infer contextual base in reference to member 'init'}}
]
.filter(\.0) // expected-error {{value of type 'Any' has no member '0'}}
// expected-note@-1 {{cast 'Any' to 'AnyObject' or use 'as!' to force downcast to a more specific type to access members}}
.prefix(3)
.map { ($0.1, $0.2) } // expected-error {{value of type 'Any' has no member '1'}} expected-error{{value of type 'Any' has no member '2'}}
// expected-note@-1 2 {{cast 'Any' to 'AnyObject' or use 'as!' to force downcast to a more specific type to access members}}
}
func reproduceC() -> [(S1, S2)] {
[
(true, .init(), .init()) // expected-error 2 {{cannot infer contextual base in reference to member 'init'}}
]
.filter(\.0) // expected-error {{value of type 'Any' has no member '0'}}
// expected-note@-1 {{cast 'Any' to 'AnyObject' or use 'as!' to force downcast to a more specific type to access members}}
.prefix(3)
.map { ($0.1, $0.2) } // expected-error {{value of type 'Any' has no member '1'}} expected-error{{value of type 'Any' has no member '2'}}
// expected-note@-1 2 {{cast 'Any' to 'AnyObject' or use 'as!' to force downcast to a more specific type to access members}}
}
}
// rdar://93103421 - Key path type inference doesn't work when the context is an existential type with a key-path superclass
extension KeyPath : P {
var member: String { "" }
}
func test_keypath_inference_from_existentials() {
struct A<T> : P {
var member: String { "a" }
var other: T { fatalError() }
}
func test<T, U>(_: any P & KeyPath<A<T>, U>, _: T) {
}
let _: any P & KeyPath<A<Int>, String> = \.member // Ok
let _: (any P & KeyPath<A<Int>, String>) = \.member // Ok
test(\.other, 42) // Ok
test(\.member, "") // Ok
}
// rdar://116376651 - key path type is bound before context is fully resolved.
func keypath_to_func_conversion_as_arg_to_overloaded_func() {
struct Data {
var value: Int = 42
}
func test<S: Sequence>(_: S, _: (S.Element) -> Int) {}
func test<C: Collection>(_: C, _: (C.Element) -> Int) {}
func test(arr: [Data]) {
test(arr, \Data.value) // Ok
}
}
// https://github.com/apple/swift/issues/55436
func test_keypath_coercion_to_function() {
struct User {
let email: String
}
let users = [User]()
let fn = \User.email as (User) -> String // Ok
_ = users.map(fn) // Ok
}
func test_keypath_application_with_composition(v: String, kp: any KeyPath<String, Int> & PP) {
_ = v[keyPath: kp] // Ok
}
func test_leading_dot_key_path_without_context() {
func test(_: AnyKeyPath?) {}
test(\.utf8)
// expected-error@-1 {{cannot infer key path type from context; consider explicitly specifying a root type}}
}
func keypath_function_transitive_conversions() {
class Base {
var derived: Derived { Derived() }
var base: Base { Base() }
var int: Int { 0 }
}
class Derived: Base {
override var derived: Derived { Derived() }
override var base: Base { Base() }
}
struct S {
var base: Base { Base() }
var derived: Derived { Derived() }
}
let _: (Base) -> Base = \Base.base
let _: (Base) -> Base = \Derived.base
let _: (Base) -> Base? = \Base?.self
let _: (Base) -> Base? = \Base?.self?.base
// FIXME: This error text is bogus due to KeyPath base covariance.
let _: (Base?) -> Base = \Base.base // expected-error {{value of optional type 'Base?' must be unwrapped to refer to member 'base' of wrapped base type 'Base'}} expected-note {{use unwrapped type 'Base' as key path root}} {{29-33=Base}}
let _: (Base) -> Base = \.base
let _: (Base) -> Base = \Base.derived
let _: (Base) -> Base = \.derived
let _: (Base) -> Int = \Base.int
let _: (Derived) -> Base = \Base.base
let _: (Derived) -> Base = \Derived.base
let _: (Derived) -> Base = \.base
let _: (Derived) -> Int = \Base.int
let _: (Derived) -> Int = \Derived.int
let _: (Derived) -> Int = \.int
let _: (Base) async throws -> Int = \.int
let _: (Derived) -> Base = \Base.derived
let _: (S) -> Base = \.derived
let _: (S) -> Derived = \.base // expected-error {{key path value type 'Base' cannot be converted to contextual type 'Derived'}}
}
func testMinimalKeypaths(_ arr: [Int?]) {
// These keypaths don't have any components that need 'resolving'. We still
// should not eagerly turn them into keypaths; they should get converted to
// functions instead
let _: [Int] = arr.compactMap(\.self)
let _: [Int] = arr.compactMap(\.?)
let _: [Int] = arr.map(\.!)
}
func testKeyPathInout() {
let _: (inout String) -> Int = \.count
let _: (inout String) -> Int = \String.count
let _: (inout String) -> Int? = \.count
func takesInout(_: (inout String) -> Int) {}
func takesInoutOpt(_: (inout String) -> Int?) {}
takesInout(\.count)
takesInout(\String.count)
takesInoutOpt(\.count)
takesInoutOpt(\String.count)
}