// RUN: %target-typecheck-verify-swift -enable-experimental-feature KeyPathWithMethodMembers -verify-additional-prefix non-resilient- // RUN: %target-typecheck-verify-swift -enable-experimental-feature KeyPathWithMethodMembers -enable-library-evolution -verify-additional-prefix resilient- // REQUIRES: swift_feature_KeyPathWithMethodMembers var global = 42 @dynamicMemberLookup struct Gettable { subscript(dynamicMember member: StaticString) -> Int { return 42 } } @dynamicMemberLookup struct Settable { subscript(dynamicMember member: StaticString) -> Int { get {return 42} set {} } } @dynamicMemberLookup struct MutGettable { subscript(dynamicMember member: StaticString) -> Int { mutating get { return 42 } } } @dynamicMemberLookup struct NonMutSettable { subscript(dynamicMember member: StaticString) -> Int { get { return 42 } nonmutating set {} } } func test(a: Gettable, b: Settable, c: MutGettable, d: NonMutSettable) { global = a.wyverns a.flavor = global // expected-error {{cannot assign through dynamic lookup property: 'a' is a 'let' constant}} global = b.flavor b.universal = global // expected-error {{cannot assign through dynamic lookup property: 'b' is a 'let' constant}} b.thing += 1 // expected-error {{left side of mutating operator isn't mutable: 'b' is a 'let' constant}} var bm = b global = bm.flavor bm.universal = global bm.thing += 1 var cm = c global = c.dragons // expected-error {{cannot use mutating getter on immutable value: 'c' is a 'let' constant}} global = c[dynamicMember: "dragons"] // expected-error {{cannot use mutating getter on immutable value: 'c' is a 'let' constant}} global = cm.dragons c.woof = global // expected-error {{cannot use mutating getter on immutable value: 'c' is a 'let' constant}} var dm = d global = d.dragons // ok global = dm.dragons // ok d.woof = global // ok dm.woof = global // ok } func testIUO(a: Gettable!, b: Settable!) { global = a.wyverns a.flavor = global // expected-error {{cannot assign through dynamic lookup property: 'a' is a 'let' constant}} global = b.flavor b.universal = global // expected-error {{cannot assign through dynamic lookup property: 'b' is a 'let' constant}} var bm: Settable! = b global = bm.flavor bm.universal = global } //===----------------------------------------------------------------------===// // Returning a function //===----------------------------------------------------------------------===// @dynamicMemberLookup struct FnTest { subscript(dynamicMember member: StaticString) -> (Int) -> () { return { x in () } } } func testFunction(x: FnTest) { x.phunky(12) } func testFunctionIUO(x: FnTest!) { x.flavor(12) } //===----------------------------------------------------------------------===// // Explicitly declared members take precedence //===----------------------------------------------------------------------===// @dynamicMemberLookup struct Dog { public var name = "Kaylee" subscript(dynamicMember member: String) -> String { return "Zoey" } } func testDog(person: Dog) -> String { return person.name + person.otherName } //===----------------------------------------------------------------------===// // Returning an IUO //===----------------------------------------------------------------------===// @dynamicMemberLookup struct IUOResult { subscript(dynamicMember member: StaticString) -> Int! { get { return 42 } nonmutating set {} } } func testIUOResult(x: IUOResult) { x.foo?.negate() // Test mutating writeback. let _: Int = x.bar // Test implicitly forced optional let b = x.bar // expected-note@-1{{short-circuit}} // expected-note@-2{{coalesce}} // expected-note@-3{{force-unwrap}} let _: Int = b // expected-error {{value of optional type 'Int?' must be unwrapped to a value of type 'Int'}} // expected-note@-1{{coalesce}} // expected-note@-2{{force-unwrap}} } //===----------------------------------------------------------------------===// // Error cases //===----------------------------------------------------------------------===// // Subscript index must be ExpressibleByStringLiteral. @dynamicMemberLookup struct Invalid1 { // expected-error @+1 {{'@dynamicMemberLookup' requires 'Invalid1' to have a 'subscript(dynamicMember:)' method that accepts either 'ExpressibleByStringLiteral' or a key path}} subscript(dynamicMember member: Int) -> Int { return 42 } } // Subscript may not be variadic. @dynamicMemberLookup struct Invalid2 { // expected-error @+1 {{'@dynamicMemberLookup' requires 'Invalid2' to have a 'subscript(dynamicMember:)' method that accepts either 'ExpressibleByStringLiteral' or a key path}} subscript(dynamicMember member: String...) -> Int { return 42 } } // References to overloads are resolved just like normal subscript lookup: // they are either contextually disambiguated or are invalid. @dynamicMemberLookup struct Ambiguity { subscript(dynamicMember member: String) -> Int { return 42 } subscript(dynamicMember member: String) -> Float { return 42 } } func testAmbiguity(a: Ambiguity) { let _: Int = a.flexibility let _: Float = a.dynamism _ = a.dynamism // expected-error {{ambiguous use of 'subscript(dynamicMember:)'}} } // expected-error @+1 {{'@dynamicMemberLookup' attribute cannot be applied to this declaration}} @dynamicMemberLookup extension Int { subscript(dynamicMember member: String) -> Int { fatalError() } } // expected-error @+1 {{'@dynamicMemberLookup' attribute cannot be applied to this declaration}} @dynamicMemberLookup func NotAllowedOnFunc() {} // @dynamicMemberLookup cannot be declared on a base class and fulfilled with a // derived class. // expected-error @+1 {{'@dynamicMemberLookup' requires 'InvalidBase' to have a 'subscript(dynamicMember:)' method that accepts either 'ExpressibleByStringLiteral' or a key path}} @dynamicMemberLookup class InvalidBase {} class InvalidDerived : InvalidBase { subscript(dynamicMember: String) -> Int { get {}} } // expected-error @+1 {{value of type 'InvalidDerived' has no member 'dynamicallyLookedUp'}} _ = InvalidDerived().dynamicallyLookedUp //===----------------------------------------------------------------------===// // Access level //===----------------------------------------------------------------------===// @dynamicMemberLookup public struct Accessible1 { public subscript(dynamicMember member: String) -> Int { return 42 } } @dynamicMemberLookup private struct Accessible2 { fileprivate subscript(dynamicMember member: String) -> Int { return 42 } } @dynamicMemberLookup open class Accessible3 { public subscript(dynamicMember member: String) -> Int { return 42 } } @dynamicMemberLookup open class Accessible4 { open subscript(dynamicMember member: String) -> Int { return 42 } } @dynamicMemberLookup public struct Accessible5 { subscript(dynamicMember member: String) -> Int { return 42 } public subscript(dynamicMember member: StaticString) -> Int { return 42 } } @dynamicMemberLookup public struct Inaccessible1 { // expected-non-resilient-warning @+2 {{'@dynamicMemberLookup' requires 'subscript(dynamicMember:)' to be as accessible as its enclosing type; this will be an error in a future Swift language mode}}{{3-3=public }} // expected-resilient-error @+1 {{'@dynamicMemberLookup' requires 'subscript(dynamicMember:)' to be as accessible as its enclosing type}}{{3-3=public }} subscript(dynamicMember member: String) -> Int { return 42 } } @dynamicMemberLookup public struct Inaccessible2 { // expected-non-resilient-warning @+2 {{'@dynamicMemberLookup' requires 'subscript(dynamicMember:)' to be as accessible as its enclosing type; this will be an error in a future Swift language mode}}{{21-29=public}} // expected-resilient-error @+1 {{'@dynamicMemberLookup' requires 'subscript(dynamicMember:)' to be as accessible as its enclosing type}}{{21-29=public}} @usableFromInline internal subscript(dynamicMember member: String) -> Int { return 42 } } @dynamicMemberLookup internal struct Inaccessible3 { // expected-non-resilient-warning @+2 {{'@dynamicMemberLookup' requires 'subscript(dynamicMember:)' to be as accessible as its enclosing type; this will be an error in a future Swift language mode}}{{3-10=internal}} // expected-resilient-error @+1 {{'@dynamicMemberLookup' requires 'subscript(dynamicMember:)' to be as accessible as its enclosing type}}{{3-10=internal}} private subscript(dynamicMember member: String) -> Int { return 42 } } @dynamicMemberLookup private struct Inaccessible4 { // expected-non-resilient-warning @+2 {{'@dynamicMemberLookup' requires 'subscript(dynamicMember:)' to be as accessible as its enclosing type; this will be an error in a future Swift language mode}}{{3-10=fileprivate}} // expected-resilient-error @+1 {{'@dynamicMemberLookup' requires 'subscript(dynamicMember:)' to be as accessible as its enclosing type}}{{3-10=fileprivate}} private subscript(dynamicMember member: String) -> Int { return 42 } } @dynamicMemberLookup public struct Inaccessible5 { internal struct Nested { } var nested: Nested // expected-non-resilient-warning @+2 {{'@dynamicMemberLookup' requires 'subscript(dynamicMember:)' to be as accessible as its enclosing type; this will be an error in a future Swift language mode}}{{3-11=public}} // expected-resilient-error @+1 {{'@dynamicMemberLookup' requires 'subscript(dynamicMember:)' to be as accessible as its enclosing type}}{{3-11=public}} internal subscript(dynamicMember keyPath: KeyPath) -> Value { nested[keyPath: keyPath] } } //===----------------------------------------------------------------------===// // Existentials //===----------------------------------------------------------------------===// @dynamicMemberLookup protocol DynamicProtocol { subscript(dynamicMember member: StaticString) -> DynamicProtocol { get nonmutating set } } struct MyDynamicStruct : DynamicProtocol { subscript(dynamicMember member: StaticString) -> DynamicProtocol { get { fatalError() } nonmutating set {} } } func testMutableExistential(a: DynamicProtocol, b: MyDynamicStruct) -> DynamicProtocol { a.x.y = b b.x.y = b return a.foo.bar.baz } // Verify protocol compositions and protocol refinements work. protocol SubDynamicProtocol : DynamicProtocol {} typealias ProtocolComp = AnyObject & DynamicProtocol func testMutableExistential2(a: AnyObject & DynamicProtocol, b: SubDynamicProtocol, c: ProtocolComp & AnyObject) { a.x.y = b b.x.y = b c.x.y = b } @dynamicMemberLookup protocol ProtoExt {} extension ProtoExt { subscript(dynamicMember member: String) -> String { get {} } } extension String: ProtoExt {} func testProtoExt() -> String { let str = "test" return str.sdfsdfsdf } //===----------------------------------------------------------------------===// // JSON example //===----------------------------------------------------------------------===// @dynamicMemberLookup enum JSON { case IntValue(Int) case StringValue(String) case ArrayValue(Array) case DictionaryValue(Dictionary) var stringValue: String? { if case .StringValue(let str) = self { return str } return nil } subscript(index: Int) -> JSON? { if case .ArrayValue(let arr) = self { return index < arr.count ? arr[index] : nil } return nil } subscript(key: String) -> JSON? { if case .DictionaryValue(let dict) = self { return dict[key] } return nil } subscript(dynamicMember member: String) -> JSON? { if case .DictionaryValue(let dict) = self { return dict[member] } return nil } } func testJsonExample(x: JSON) -> String? { _ = x.name?.first return x.name?.first?.stringValue } //===----------------------------------------------------------------------===// // Class inheritance tests //===----------------------------------------------------------------------===// @dynamicMemberLookup class BaseClass { subscript(dynamicMember member: String) -> Int { return 42 } } class DerivedClass : BaseClass {} func testDerivedClass(x: BaseClass, y: DerivedClass) -> Int { return x.life - y.the + x.universe - y.and + x.everything } // Test that derived classes can add a setter. class DerivedClassWithSetter : BaseClass { override subscript(dynamicMember member: String) -> Int { get { return super[dynamicMember: member] } set {} } } func testOverrideSubscript(a: BaseClass, b: DerivedClassWithSetter) { let x = a.frotz + b.garbalaz b.baranozo = x a.balboza = 12 // expected-error {{cannot assign through dynamic lookup property: 'a' is a 'let' constant}} } //===----------------------------------------------------------------------===// // Generics //===----------------------------------------------------------------------===// @dynamicMemberLookup struct SettableGeneric1 { subscript(dynamicMember member: StaticString) -> T? { get {} nonmutating set {} } } func testGenericType(a: SettableGeneric1, b: T) -> T? { a.dfasdf = b return a.dfsdffff } func testConcreteGenericType(a: SettableGeneric1) -> Int? { a.dfasdf = 42 return a.dfsdffff } @dynamicMemberLookup struct SettableGeneric2 { subscript(dynamicMember member: U) -> T { get {} nonmutating set {} } } func testGenericType2(a: SettableGeneric2, b: T) -> T? { a[dynamicMember: "fasdf"] = b a.dfasdf = b return a.dfsdffff } func testConcreteGenericType2(a: SettableGeneric2) -> Int? { a.dfasdf = 42 return a.dfsdffff } /// https://github.com/apple/swift/issues/50610 /// `subscript(dynamicMember:)` works as a `@dynamicMemberLookup` protocol /// requirement @dynamicMemberLookup protocol GenericProtocol { associatedtype S: ExpressibleByStringLiteral associatedtype T subscript(dynamicMember member: S) -> T { get } } @dynamicMemberLookup class GenericClass { let t: T init(_ t: T) { self.t = t } subscript(dynamicMember member: S) -> T { return t } } func testGenerics( a: P, b: AnyObject & GenericClass ) where P.S == S, P.T == T { let _: T = a.wew let _: T = b.lad } //===----------------------------------------------------------------------===// // Keypaths //===----------------------------------------------------------------------===// @dynamicMemberLookup class KP { subscript(dynamicMember member: String) -> Int { return 7 } } _ = \KP.[dynamicMember: "hi"] _ = \KP.testLookup /* KeyPath based dynamic lookup */ struct Point { var x: Int let y: Int // expected-note 2 {{change 'let' to 'var' to make it mutable}} private let z: Int = 0 // expected-note 10 {{declared here}} } struct Rectangle { var topLeft, bottomRight: Point } @dynamicMemberLookup struct Lens { var obj: T init(_ obj: T) { self.obj = obj } subscript(dynamicMember member: KeyPath) -> Lens { get { return Lens(obj[keyPath: member]) } } subscript(dynamicMember member: WritableKeyPath) -> Lens { get { return Lens(obj[keyPath: member]) } set { obj[keyPath: member] = newValue.obj } } } var topLeft = Point(x: 0, y: 0) var bottomRight = Point(x: 10, y: 10) var lens = Lens(Rectangle(topLeft: topLeft, bottomRight: bottomRight)) _ = lens.topLeft _ = lens.topLeft.x _ = lens.topLeft.y _ = lens.topLeft.z // expected-error {{'z' is inaccessible due to 'private' protection level}} _ = lens.bottomRight _ = lens.bottomRight.x _ = lens.bottomRight.y _ = lens.bottomRight.z // expected-error {{'z' is inaccessible due to 'private' protection level}} _ = \Lens.x _ = \Lens.y _ = \Lens.z // expected-error {{'z' is inaccessible due to 'private' protection level}} _ = \Lens.topLeft.x _ = \Lens.topLeft.y _ = \Lens.topLeft.z // expected-error {{'z' is inaccessible due to 'private' protection level}} _ = \Lens<[Int]>.count _ = \Lens<[Int]>.[0] _ = \Lens<[[Int]]>.[0].count lens.topLeft = Lens(Point(x: 1, y: 2)) // Ok lens.bottomRight.x = Lens(11) // Ok lens.bottomRight.y = Lens(12) // expected-error {{cannot assign to property: 'y' is a 'let' constant}} lens.bottomRight.z = Lens(13) // expected-error {{'z' is inaccessible due to 'private' protection level}} func acceptKeyPathDynamicLookup(_: Lens) {} acceptKeyPathDynamicLookup(lens.topLeft.x) acceptKeyPathDynamicLookup(lens.topLeft.y) acceptKeyPathDynamicLookup(lens.topLeft.z) // expected-error {{'z' is inaccessible due to 'private' protection level}} var tupleLens = Lens<(String, Int)>(("ultimate question", 42)) _ = tupleLens.0.count _ = tupleLens.1 var namedTupleLens = Lens<(question: String, answer: Int)>((question: "ultimate question", answer: 42)) _ = namedTupleLens.question.count _ = namedTupleLens.answer struct MethodAndInitializerTest { let value: Int init(value: Int) { self.value = value } func instanceMethod() -> String { return "InstanceMethod" } static func staticMethod() -> Int { return 42 } } @dynamicMemberLookup struct MethodAndInitializerLens { var value: T var type: T.Type subscript(dynamicMember member: KeyPath) -> U { return value[keyPath: member] } subscript(dynamicMember member: (T) -> () -> U) -> () -> U { return { member(self.value)() } } subscript(dynamicMember member: (T.Type) -> () -> U) -> () -> U { return { member(self.type)() } } } func test_method_and_init_lens() { let instance = MethodAndInitializerTest(value: 10) let methodLens = MethodAndInitializerLens(value: instance, type: MethodAndInitializerTest.self) let _ = methodLens[dynamicMember: MethodAndInitializerTest.instanceMethod]() let staticMethodClosure = methodLens[dynamicMember: { $0.staticMethod }] let _ = staticMethodClosure() let initializer = MethodAndInitializerTest.init let _ = MethodAndInitializerLens(value: initializer(20), type: MethodAndInitializerTest.self) } @dynamicMemberLookup class A { var value: T init(_ v: T) { self.value = v } subscript(dynamicMember member: KeyPath) -> U { get { return value[keyPath: member] } } } @dynamicMemberLookup class AMetatype { var value: T.Type init(_ v: T.Type) { self.value = v } subscript(dynamicMember member: KeyPath) -> U { get { return value[keyPath: member] } } } // Let's make sure that keypath dynamic member lookup // works with inheritance class B : A {} func bar(_ b: B) { let _: Int = b.x let _ = b.y let _: Float = b.y // expected-error {{cannot convert value of type 'Int' to specified type 'Float'}} let _ = b.z // expected-error {{'z' is inaccessible due to 'private' protection level}} } // Existentials and IUOs @dynamicMemberLookup protocol KeyPathLookup { associatedtype T var value: T { get } subscript(dynamicMember member: KeyPath) -> Int! { get } } extension KeyPathLookup { subscript(dynamicMember member: KeyPath) -> Int! { get { return value[keyPath: member] } } } class C : KeyPathLookup { var value: T init(_ v: T) { self.value = v } } func baz(_ c: C) { let _: Int = c.x let _ = c.y let _: Float = c.y // expected-error {{cannot convert value of type 'Int?' to specified type 'Float'}} let _ = c.z // expected-error {{'z' is inaccessible due to 'private' protection level}} } @dynamicMemberLookup class D { var value: T init(_ v: T) { self.value = v } subscript(dynamicMember member: KeyPath) -> (U) -> U { get { return { offset in self.value[keyPath: member] + offset } } } } func faz(_ d: D) { let _: Int = d.x(42) let _ = d.y(1 + 0) let _: Float = d.y(1 + 0) // expected-error {{cannot convert value of type 'Int' to specified type 'Float'}} let _ = d.z(1 + 0) // expected-error {{'z' is inaccessible due to 'private' protection level}} } @dynamicMemberLookup struct SubscriptLens { var value: T var counter: Int = 0 subscript(foo: String) -> Int { get { return 42 } } subscript(offset: Int) -> Int { get { return counter } set { counter = counter + newValue } } subscript(dynamicMember member: KeyPath) -> U! { get { return value[keyPath: member] } } subscript(dynamicMember member: WritableKeyPath) -> U { get { return value[keyPath: member] } set { value[keyPath: member] = newValue } } } func keypath_with_subscripts(_ arr: SubscriptLens<[Int]>, _ dict: inout SubscriptLens<[String: Int]>) { _ = arr[0..<3] for idx in 0..>) { for idx in 0..' to expected argument type 'Int'}} let _ = arr[idx] } } struct WithTrailingClosure { subscript(fn: () -> Int) -> Int { get { return fn() } nonmutating set { _ = fn() + newValue } } subscript(offset: Int, _ fn: () -> Int) -> Int { get { return offset + fn() } } } func keypath_with_trailing_closure_subscript(_ ty: inout SubscriptLens) { _ = ty[0] { 42 } // expected-error {{subscript index of type '() -> Int' in a key path must be Hashable}} _ = ty[0] { 42 } = 0 // expected-error {{cannot assign through subscript: subscript is get-only}} // expected-error@-1 {{subscript index of type '() -> Int' in a key path must be Hashable}} _ = ty[] { 42 } // expected-error {{subscript index of type '() -> Int' in a key path must be Hashable}} _ = ty[] { 42 } = 0 // expected-error {{subscript index of type '() -> Int' in a key path must be Hashable}} } func keypath_to_subscript_to_property(_ lens: inout Lens>) { _ = lens[0].topLeft.x _ = lens[0].topLeft.y _ = lens[0].topLeft.x = Lens(0) _ = lens[0].topLeft.y = Lens(1) // expected-error@-1 {{cannot assign to property: 'y' is a 'let' constant}} } @dynamicMemberLookup struct SingleChoiceLens { var obj: T init(_ obj: T) { self.obj = obj } subscript(dynamicMember member: WritableKeyPath) -> U { get { return obj[keyPath: member] } set { obj[keyPath: member] = newValue } } } // Make sure that disjunction filtering optimization doesn't // impede keypath dynamic member lookup by eagerly trying to // simplify disjunctions with a single viable choice. func test_lens_with_a_single_choice(a: inout SingleChoiceLens<[Int]>) { a[0] = 1 // Ok } func test_chain_of_recursive_lookups(_ lens: Lens>>) { _ = lens.x _ = lens.y _ = lens.z // expected-error {{'z' is inaccessible due to 'private' protection level}} // Make sure that 'obj' field could be retrieved at any level _ = lens.obj _ = lens.obj.obj _ = lens.obj.x _ = lens.obj.obj.x _ = \Lens>.x _ = \Lens>.obj.x } // KeyPath Dynamic Member Lookup can't refer mutating setters because of the // KeyPath limitations func invalid_refs_through_dynamic_lookup() { struct S { static var foo: Int = 42 func bar() -> Q { return Q() } static func baz(_: String) -> Int { return 0 } } struct Q { var faz: Int = 0 } func test(_ lens: A) { _ = lens.foo // expected-error {{static member 'foo' cannot be used on instance of type 'S'}} _ = lens.bar() _ = lens.bar().faz + 1 _ = lens.baz("hello") // expected-error {{static member 'baz' cannot be used on instance of type 'S'}} } func testStatic(_ lens: AMetatype) { _ = lens.foo _ = lens.baz("hello") } } // https://github.com/apple/swift/issues/52997 final class C1_52997 {} @dynamicMemberLookup struct S1_52997 { var obj: T init(_ obj: T) { self.obj = obj } subscript(dynamicMember member: KeyPath) -> U { return obj[keyPath: member] } var wooo: C1_52997 { C1_52997() } // expected-note {{declared here}} } do { _ = S1_52997(C1_52997()).wooooo // expected-error@-1 {{value of type 'S1_52997' has no dynamic member 'wooooo' using key path from root type 'C1_52997'; did you mean 'wooo'?}} _ = S1_52997(C1_52997()).bla // expected-error@-1 {{value of type 'S1_52997' has no dynamic member 'bla' using key path from root type 'C1_52997'}} } final class C2_52997 { var woo: Int? // expected-note 2 {{'woo' declared here}} } @dynamicMemberLookup struct S2_52997 { var obj: T init(_ obj: T) { self.obj = obj } subscript(dynamicMember member: KeyPath) -> U { return obj[keyPath: member] } } do { _ = S2_52997(C2_52997()).wooo // expected-error@-1 {{value of type 'S2_52997' has no dynamic member 'wooo' using key path from root type 'C2_52997'; did you mean 'woo'?}} _ = S2_52997(C2_52997()).bla // expected-error@-1 {{value of type 'S2_52997' has no dynamic member 'bla' using key path from root type 'C2_52997'}} } // https://github.com/apple/swift/issues/52957 @dynamicMemberLookup struct S1_52957 { subscript(dynamicMember: String) -> String { // expected-error {{'@dynamicMemberLookup' requires 'S1_52957' to have a 'subscript(dynamicMember:)' method that accepts either 'ExpressibleByStringLiteral' or a key path}} // expected-note@-1 {{add an explicit argument label to this subscript to satisfy the '@dynamicMemberLookup' requirement}}{{13-13=dynamicMember }} fatalError() } } @dynamicMemberLookup struct S2_52957 { subscript(foo bar: String) -> String { // expected-error {{'@dynamicMemberLookup' requires 'S2_52957' to have a 'subscript(dynamicMember:)' method that accepts either 'ExpressibleByStringLiteral' or a key path}} fatalError() } subscript(foo: String) -> String { // expected-error {{'@dynamicMemberLookup' requires 'S2_52957' to have a 'subscript(dynamicMember:)' method that accepts either 'ExpressibleByStringLiteral' or a key path}} // expected-note@-1 {{add an explicit argument label to this subscript to satisfy the '@dynamicMemberLookup' requirement}} {{13-13=dynamicMember }} fatalError() } } // https://github.com/apple/swift/issues/54292 @dynamicMemberLookup struct S_54292 { subscript(dynamicMember member: Substring) -> Int { 0 } } do { _ = \S_54292.okay } func test_infinite_self_recursion() { @dynamicMemberLookup struct Recurse { subscript(dynamicMember member: KeyPath, U>) -> Int { return 1 } } _ = Recurse().foo // expected-error@-1 {{value of type 'Recurse' has no dynamic member 'foo' using key path from root type 'Recurse'}} } // rdar://problem/60225883 - crash during solution application (ExprRewriter::buildKeyPathDynamicMemberIndexExpr) func test_combination_of_keypath_and_string_lookups() { @dynamicMemberLookup struct Outer { subscript(dynamicMember member: String) -> Outer { Outer() } subscript(dynamicMember member: KeyPath) -> Outer { Outer() } } @dynamicMemberLookup struct Inner { subscript(dynamicMember member: String) -> Inner { Inner() } } func test(outer: Outer) { _ = outer.hello.world // Ok } } // https://github.com/apple/swift/issues/55070 @dynamicMemberLookup struct S_55070 { var i: Int subscript(dynamicMember member: KeyPath) -> Int { get { self[keyPath: member] } set { self[keyPath: member] = newValue } // expected-error {{cannot assign through subscript: 'member' is a read-only key path}} } } // https://github.com/apple/swift/issues/54864 public struct S1_54864 {} @dynamicMemberLookup public struct S2_54864 {} internal var s2_54864_instance: S2_54864 = S2_54864() public extension S2_54864 { subscript(dynamicMember member: WritableKeyPath) -> T { get { s2_54864_instance[keyPath: member] } // expected-error {{key path with root type 'S1_54864' cannot be applied to a base of type 'S2_54864'}} set { s2_54864_instance[keyPath: member] = newValue } // expected-error {{key path with root type 'S1_54864' cannot be applied to a base of type 'S2_54864'}} } } @dynamicMemberLookup public struct S3_54864 {} public extension S3_54864 { subscript(dynamicMember member: KeyPath) -> T { get { s2_54864_instance[keyPath: member] } // expected-error {{key path with root type 'S3_54864' cannot be applied to a base of type 'S2_54864'}} } } // https://github.com/swiftlang/swift/issues/75244 struct WithSendable { subscript(dynamicMember member: KeyPath & Sendable) -> Bool { // Ok get { false } } } // Make sure we enforce a limit on the number of chained dynamic member lookups. @dynamicMemberLookup struct SelfRecursiveLookup { init(_: () -> T) {} init(_: () -> KeyPath) {} subscript(dynamicMember kp: KeyPath) -> SelfRecursiveLookup {} } let selfRecurse1 = SelfRecursiveLookup { selfRecurse1.e } // expected-error@-1 {{could not find member 'e'; exceeded the maximum number of nested dynamic member lookups}} let selfRecurse2 = SelfRecursiveLookup { selfRecurse2[a: 0] } // expected-error@-1 {{could not find member 'subscript'; exceeded the maximum number of nested dynamic member lookups}} let selfRecurse3 = SelfRecursiveLookup { \.e } // expected-error@-1 {{could not find member 'e'; exceeded the maximum number of nested dynamic member lookups}} let selfRecurse4 = SelfRecursiveLookup { \.[a: 0] } // expected-error@-1 {{could not find member 'subscript'; exceeded the maximum number of nested dynamic member lookups}} extension SelfRecursiveLookup where T == SelfRecursiveLookup>> { var terminator: T { fatalError() } subscript(terminator terminator: Int) -> T { fatalError() } } let selfRecurse5 = SelfRecursiveLookup { selfRecurse5.terminator } let selfRecurse6 = SelfRecursiveLookup { selfRecurse6[terminator: 0] } let selfRecurse7 = SelfRecursiveLookup { \.terminator } let selfRecurse8 = SelfRecursiveLookup { \.[terminator: 0] }