// RUN: %batch-code-completion struct Point { var x: Int var y: Int } struct Rectangle { var topLeft: Point var bottomRight: Point } @dynamicMemberLookup struct Lens { var obj: T init(_ obj: T) { self.obj = obj } subscript(dynamicMember member: WritableKeyPath) -> Lens { get { return Lens(obj[keyPath: member]) } set { obj[keyPath: member] = newValue.obj } } } func testMembersPostfix1(r: Lens) { r#^testMembersPostfix1^# } // testMembersPostfix1-DAG: Decl[Subscript]/CurrNominal: [{#dynamicMember: WritableKeyPath#}][#Lens#]; // testMembersPostfix1-DAG: Decl[InstanceVar]/CurrNominal: .topLeft[#Lens#]; // testMembersPostfix1-DAG: Decl[InstanceVar]/CurrNominal: .bottomRight[#Lens#]; func testMembersDot1(r: Lens) { r.#^testMembersDot1^# } // testMembersDot1-DAG: Decl[InstanceVar]/CurrNominal: topLeft[#Lens#]; // testMembersDot1-DAG: Decl[InstanceVar]/CurrNominal: bottomRight[#Lens#]; func testMembersDot2(r: Lens) { r.topLeft.#^testMembersDot2^# } // testMembersDot2-DAG: Decl[InstanceVar]/CurrNominal: x[#Lens#]; // testMembersDot2-DAG: Decl[InstanceVar]/CurrNominal: y[#Lens#]; @dynamicMemberLookup struct MultipleSubscript { subscript(dynamicMember member: KeyPath) -> U { return Point(x: 1, y: 2)[keyPath: member] } subscript(dynamicMember member: KeyPath) -> U { return Rectangle(topLeft: Point(x: 0, y: 0), bottomRight: Point(x: 1, y: 1))[keyPath: member] } } func testMultipleSubscript1(r: MultipleSubscript) { r.#^testMultipleSubscript1^# } // testMultipleSubscript1-DAG: Decl[InstanceVar]/CurrNominal: x[#Int#]; // testMultipleSubscript1-DAG: Decl[InstanceVar]/CurrNominal: y[#Int#]; // testMultipleSubscript1-DAG: Decl[InstanceVar]/CurrNominal: topLeft[#Point#]; // testMultipleSubscript1-DAG: Decl[InstanceVar]/CurrNominal: bottomRight[#Point#]; @dynamicMemberLookup class Base { var t: T init(_ t: T) { self.t = t } subscript(dynamicMember member: KeyPath) -> U { return t[keyPath: member] } } class Inherit1: Base {} func testInherit1(r: Inherit1) { r.#^testInherit1^# } // testInherit1-DAG: Decl[InstanceVar]/CurrNominal: x[#Int#]; // testInherit1-DAG: Decl[InstanceVar]/CurrNominal: y[#Int#]; class Inherit2: Base { var u: U init(_ t: T, _ u: U) { super.init(t); self.u = u } subscript(dynamicMember member: KeyPath) -> V { return u[keyPath: member] } } func testInherit2(r: Inherit2) { r.#^testInherit2^# } // testInherit2-DAG: Decl[InstanceVar]/CurrNominal: x[#Int#]; // testInherit2-DAG: Decl[InstanceVar]/CurrNominal: y[#Int#]; // testInherit2-DAG: Decl[InstanceVar]/CurrNominal: topLeft[#Point#]; // testInherit2-DAG: Decl[InstanceVar]/CurrNominal: bottomRight[#Point#]; class Shadow1: Base { var x: String = "" } func testShadow1(r: Shadow1) { r.#^testShadow1^# } // testShadow1-NOT: x[#Int#]; // testShadow1: Decl[InstanceVar]/CurrNominal: y[#Int#]; // testShadow1-NOT: x[#Int#]; // testShadow1: Decl[InstanceVar]/CurrNominal: x[#String#]; @dynamicMemberLookup protocol P { associatedtype T subscript(dynamicMember member: KeyPath) -> U } func testGeneric1(r: G) where G.T == Point { r.#^testGeneric1^# } // testGeneric1-DAG: Decl[InstanceVar]/CurrNominal: x[#Int#]; // testGeneric1-DAG: Decl[InstanceVar]/CurrNominal: y[#Int#]; func testGenericUnderconstrained1(r: G) { r.#^testGenericUnderconstrained1^# } // testGenericUnderconstrained1-NOT: CurrNominal // testGenericUnderconstrained1: Keyword[self]/CurrNominal: self[#{{any P|G}}#]; // testGenericUnderconstrained1-NOT: CurrNominal func testExistential1(r: P) { r.#^testExistential1?check=testGenericUnderconstrained1^# } @dynamicMemberLookup protocol E { subscript(dynamicMember member: KeyPath) -> U } func testExistential2(r: E) { r.#^testExistential2^# } // testExistential2-DAG: Decl[InstanceVar]/CurrNominal: x[#Int#]; // testExistential2-DAG: Decl[InstanceVar]/CurrNominal: y[#Int#]; struct WithP: P { var t: T init(t: T) { self.t = t } subscript(dynamicMember member: KeyPath) -> U { return t[keyPath: member] } } func testProtocolConform1(r: WithP) { r.#^testProtocolConform1^# } // testProtocolConform1-DAG: Decl[InstanceVar]/CurrNominal: x[#Int#]; // testProtocolConform1-DAG: Decl[InstanceVar]/CurrNominal: y[#Int#]; @dynamicMemberLookup struct OnSelf { subscript(dynamicMember member: KeyPath) -> U { return Point(x: 0, y: 1)[keyPath: member] } func test() { self.#^OnSelf1^# } } // OnSelf1-DAG: Decl[InstanceMethod]/CurrNominal: test()[#Void#]; // OnSelf1-DAG: Decl[InstanceVar]/CurrNominal: x[#Int#]; // OnSelf1-DAG: Decl[InstanceVar]/CurrNominal: y[#Int#]; protocol HalfRect { var topLeft: Point } extension Lens where T: HalfRect { func testSelfExtension1() { self.#^testSelfExtension1^# } } // testSelfExtension1-NOT: bottomRight // testSelfExtension1: Decl[InstanceVar]/CurrNominal: topLeft[#Lens#]; // testSelfExtension1-NOT: bottomRight struct Invalid1 { subscript(dynamicMember member: KeyPath) -> U { return Point(x: 0, y: 1)[keyPath: member] } } func testInvalid1(r: Invalid1) { r.#^testInvalid1^# } // testInvalid1-NOT: topLeft @dynamicMemberLookup struct Invalid2 { subscript(dynamicMember: KeyPath) -> U { return Point(x: 0, y: 1)[keyPath: dynamicMember] } } func testInvalid2(r: Invalid2) { r.#^testInvalid2^# } // testInvalid2-NOT: topLeft @dynamicMemberLookup struct Invalid3 { subscript(dynamicMember member: Rectangle) -> U { return Point(x: 0, y: 1)[keyPath: member] } } func testInvalid3(r: Invalid3) { r.#^testInvalid3^# } // testInvalid3-NOT: topLeft struct NotKeyPath {} @dynamicMemberLookup struct Invalid4 { subscript(dynamicMember member: NotKeyPath) -> U { return Point(x: 0, y: 1)[keyPath: member] } } func testInvalid4(r: Invalid4) { r.#^testInvalid4^# } // testInvalid4-NOT: topLeft struct Gen1 { var foo: T } @dynamicMemberLookup struct GenericRoot { subscript(dynamicMember member: KeyPath, U>) -> Int { return 1 } } func testGenericRoot1(r: GenericRoot) { r.#^testGenericRoot1^# } // testGenericRoot1: Decl[InstanceVar]/CurrNominal: foo[#Int#]; @dynamicMemberLookup struct GenericResult { subscript(dynamicMember member: KeyPath>) -> GenericResult { fatalError() } } struct BoxedCircle { var center: Gen1 var radius: Gen1 } func testGenericResult1(r: GenericResult) { r.#^testGenericResult1^# } // FIXME: the type should be 'GenericResult' // testGenericResult1-DAG: Decl[InstanceVar]/CurrNominal: center[#Gen1#]; name=center // testGenericResult1-DAG: Decl[InstanceVar]/CurrNominal: radius[#Gen1#]; name=radius class C { var someUniqueName: Int = 0 } @dynamicMemberLookup struct AnyObjectRoot { subscript(dynamicMember member: KeyPath) -> Int { return 1 } } func testAnyObjectRoot1(r: AnyObjectRoot) { r.#^testAnyObjectRoot1^# } // Do not do find via AnyObject dynamic lookup. // testAnyObjectRoot1-NOT: someUniqueName func testNested1(r: Lens>) { r.#^testNested1^# // FIXME: The type should be 'Lens>' // testNested1-DAG: Decl[InstanceVar]/CurrNominal: x[#Lens#]; // testNested1-DAG: Decl[InstanceVar]/CurrNominal: y[#Lens#]; } func testNested2(r: Lens>>) { r.#^testNested2^# // FIXME: The type should be 'Lens>>' // testNested2-DAG: Decl[InstanceVar]/CurrNominal: x[#Lens#]; // testNested2-DAG: Decl[InstanceVar]/CurrNominal: y[#Lens#]; } @dynamicMemberLookup struct Recurse { var obj: T init(_ obj: T) { self.obj = obj } subscript(dynamicMember member: KeyPath, U>) -> Int { return 1 } } func testCycle1(r: Recurse) { r.#^testCycle1^# // testCycle1: Begin completions // testCycle1-NOT: x[#Int#] } @dynamicMemberLookup struct CycleA { var fromA: Int subscript(dynamicMember member: KeyPath, U>) -> Int { return 1 } } @dynamicMemberLookup struct CycleB { var fromB: Int subscript(dynamicMember member: KeyPath, U>) -> Int { return 1 } } @dynamicMemberLookup struct CycleC { var fromC: Int subscript(dynamicMember member: KeyPath, U>) -> Int { return 1 } } func testCycle2(r: CycleA) { r.#^testCycle2^# // testCycle2: Begin completions } protocol DynamicLookupProto { associatedtype Content } extension DynamicLookupProto { subscript(dynamicMember key: KeyPath) -> T { fatalError() } } @dynamicMemberLookup struct DynamicLookupConcrete : DynamicLookupProto { typealias Content = Point } func testSubscriptOnProtocolExtension(dyn: DynamicLookupConcrete) { dyn.#^testSubscriptOnProtocolExt^# // testSubscriptOnProtocolExt: Keyword[self]/CurrNominal: self[#DynamicLookupConcrete#]; // testSubscriptOnProtocolExt: Decl[InstanceVar]/CurrNominal: x[#Int#]; // testSubscriptOnProtocolExt: Decl[InstanceVar]/CurrNominal: y[#Int#]; } // https://github.com/swiftlang/swift/issues/77035 @dynamicMemberLookup struct HasSendableKeyPath { subscript(dynamicMember keyPath: KeyPath & Sendable) -> HasSendableKeyPath { fatalError() } } func testSendableKeyPath(_ x: HasSendableKeyPath) { x.#^SENDABLE_KEYPATH_POINT^# // SENDABLE_KEYPATH_POINT-DAG: Decl[InstanceVar]/CurrNominal: x[#HasSendableKeyPath#]; name=x // SENDABLE_KEYPATH_POINT-DAG: Decl[InstanceVar]/CurrNominal: y[#HasSendableKeyPath#]; name=y }