diff --git a/proposals/0438-metatype-keypath.md b/proposals/0438-metatype-keypath.md index 94b2bdb954..0a950a6015 100644 --- a/proposals/0438-metatype-keypath.md +++ b/proposals/0438-metatype-keypath.md @@ -1,4 +1,4 @@ -# Metatype Keypaths +# Metatype Key Paths * Proposal: [SE-0438](0438-metatype-keypath.md) * Authors: [Amritpan Kaur](https://github.com/amritpan), [Pavel Yaskevich](https://github.com/xedin) @@ -9,15 +9,15 @@ ## Introduction -Key path expressions access properties dynamically. They are declared with a concrete root type and one or more key path components that define a path to a resulting value via the type’s properties, subscripts, optional-chaining expressions, forced unwrapped expressions, or self. This proposal expands key path expression access to include static properties of a type, i.e., metatype keypaths. +Key path expressions access properties dynamically. They are declared with a concrete root type and one or more key path components that define a path to a resulting value via the type’s properties, subscripts, optional-chaining expressions, forced unwrapped expressions, or self. This proposal expands key path expression access to include static properties of a type, i.e., metatype key paths. ## Motivation -Metatype keypaths were briefly explored in the pitch for [SE-0254](https://forums.swift.org/t/pitch-static-and-class-subscripts/21850) and the [proposal](https://github.com/swiftlang/swift-evolution/blob/main/proposals/0254-static-subscripts.md#metatype-key-paths) later recommended them as a future direction. Allowing key path expressions to directly refer to static properties has also been discussed on the Swift Forums for database lookups when used [in conjunction with @dynamicMemberLookup](https://forums.swift.org/t/dynamic-key-path-member-lookup-cannot-refer-to-static-member/30212) and as a way to avoid verbose hacks like [referring to a static property through another computed property](https://forums.swift.org/t/key-path-cannot-refer-to-static-member/28055). Supporting metatype keypaths in the Swift language will address these challenges and improve language semantics. +Metatype key paths were briefly explored in the pitch for [SE-0254](https://forums.swift.org/t/pitch-static-and-class-subscripts/21850) and the [proposal](https://github.com/apple/swift-evolution/blob/main/proposals/0254-static-subscripts.md#metatype-key-paths) later recommended them as a future direction. Allowing key path expressions to directly refer to static properties has also been discussed on the Swift Forums for database lookups when used [in conjunction with @dynamicMemberLookup](https://forums.swift.org/t/dynamic-key-path-member-lookup-cannot-refer-to-static-member/30212) and as a way to avoid verbose hacks like [referring to a static property through another computed property](https://forums.swift.org/t/key-path-cannot-refer-to-static-member/28055). Supporting metatype key paths in the Swift language will address these challenges and improve language semantics. ## Proposed solution -We propose to allow keypath expressions to define a reference to static properties. The following usage, which currently generates a compiler error, will be allowed as valid Swift code. +We propose to allow key path expressions to define a reference to static properties. The following usage, which currently generates a compiler error, will be allowed as valid Swift code. ```swift struct Bee { @@ -31,7 +31,7 @@ let kp = \Bee.Type.name ### Metatype syntax -Keypath expressions where the first component refers to a static property will include `.Type` on their root types stated in the key path contextual type or in the key path literal. For example: +Key path expressions where the first component refers to a static property will include `.Type` on their root types stated in the key path contextual type or in the key path literal. For example: ```swift struct Bee { @@ -42,13 +42,13 @@ let kpWithContextualType: KeyPath = \.name // key path context let kpWithLiteral = \Bee.Type.name // key path literal \Bee.Type ``` -Attempting to write the above metatype keypath without including `.Type will trigger an error diagnostic: +Attempting to write the above metatype key path without including `.Type` will trigger an error diagnostic with a fix-it recommending the addition of `Type` after the root type `Bee`: ```swift let kpWithLiteral = \Bee.name // error: static member 'name' cannot be used on instance of type 'Bee' ``` -Keypath expressions where the component referencing a static property is not the first component do not require `.Type`: +Key path expressions where the component referencing a static property is not the first component do not require `.Type`: ```swift struct Species { static let isNative = true @@ -62,7 +62,7 @@ let kpSecondComponentIsStatic = \Wasp.species.isNative ``` ### Access semantics -Immutable static properties will form the read-only keypaths just like immutable instance properties. +Immutable static properties will form the read-only key paths just like immutable instance properties. ```swift struct Tip { static let isIncluded = True @@ -72,7 +72,7 @@ struct Tip { let kpStaticImmutable: KeyPath = \.isIncluded let kpInstanceImmutable: KeyPath = \.isVoluntary ``` -However, unlike instance members, keypaths to mutable static properties will always conform to `ReferenceWritableKeyPath` because metatypes are reference types. +However, unlike instance members, key paths to mutable static properties will always conform to `ReferenceWritableKeyPath` because metatypes are reference types. ```swift struct Tip { static var total = 0 @@ -84,7 +84,7 @@ let kpInstanceMutable: WriteableKeyPath = \.flatRate ``` ## Effect on source compatibility -This feature breaks source compatibility for key path expressions that reference static properties after subscript overloads. For example, the compiler cannot differentiate between subscript keypath components by return type in the following: +This feature breaks source compatibility for key path expressions that reference static properties after subscript overloads. For example, the compiler cannot differentiate between subscript key path components by return type in the following: ```swift struct S { @@ -99,7 +99,7 @@ struct Test { let kpViaSubscript = \Test.[42] // fails to typecheck ``` -This keypath does not specify a contextual type, without which the key path value type is unknown. To form a keypath to the metatype subscript and return an `Int`, we can specify a contextual type with a value type of `S.Type` and chain the metatype keypath: +This key path does not specify a contextual type, without which the key path value type is unknown. To form a key path to the metatype subscript and return an `Int`, we can specify a contextual type with a value type of `S.Type` and chain the metatype key path: ```swift let kpViaSubscript: KeyPath = \Test.[42] @@ -125,11 +125,11 @@ note: rebuild to enable the feature ## Future directions -### Key Paths to Enum cases +### Key paths to enum cases Adding language support for read-only key paths to enum cases has been widely discussed on the [Swift Forums](https://forums.swift.org/t/enum-case-key-paths-an-update/68436) but has been left out of this proposal as this merits a separate discussion around [syntax design and implementation concerns](https://forums.swift.org/t/enum-case-keypaths/60899/32). -Since references to enum cases must be metatypes, extending keypath expressions to include references to metatypes will hopefully bring the Swift language closer to adopting keypaths to enum cases in a future pitch. +Since references to enum cases must be metatypes, extending key path expressions to include references to metatypes will hopefully bring the Swift language closer to adopting key paths to enum cases in a future pitch. ## Acknowledgments