Skip to content

Commit 8755494

Browse files
slbenrimmington
andauthored
Apply suggestions from code review
Co-authored-by: Ben Rimmington <[email protected]>
1 parent cc97591 commit 8755494

File tree

1 file changed

+34
-20
lines changed

1 file changed

+34
-20
lines changed

proposals/xxxx-extend-generic-static-member-lookup.md

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -113,27 +113,32 @@ There are ways of achieving the desired syntax today without changing the langua
113113
When SwiftUI was still in beta, it included one such workaround in the form of the `StaticMember` type:
114114

115115
```swift
116-
protocol ToggleStyle {
116+
// Rejected SwiftUI APIs:
117+
118+
public protocol ToggleStyle {
117119
// ...
118120
typealias Member = StaticMember<Self>
119121
}
120122

121-
struct StaticMember<Base> {
122-
var base: Base
123-
init(_ base: Base)
123+
extension View {
124+
public func toggleStyle<S: ToggleStyle>(_ style: S.Member) -> some View
124125
}
125126

126-
extension StaticMember where Base: ToggleStyle {
127-
static var switch: StaticMember<SwitchToggleStyle> { .init(.init()) }
128-
static var checkbox: StaticMember<CheckboxToggleStyle> { .init(.init()) }
127+
public struct StaticMember<Base> {
128+
public var base: Base
129+
public init(_ base: Base)
129130
}
130131

131-
extension View {
132-
func toggleStyle<S : ToggleStyle>(_ style: S.Member) -> some View
132+
extension StaticMember where Base: ToggleStyle {
133+
public static var `default`: StaticMember<DefaultToggleStyle> { get }
134+
public static var `switch`: StaticMember<SwitchToggleStyle> { get }
135+
public static var checkbox: StaticMember<CheckboxToggleStyle> { get }
133136
}
134137

135-
MyView().toggleStyle(.switch)
136-
MyView().toggleStyle(.checkbox)
138+
// Leading dot syntax (using rejected workaround):
139+
140+
Toggle("Wi-Fi", isOn: $isWiFiEnabled)
141+
.toggleStyle(.switch)
137142
```
138143

139144
However, `StaticMember` *serves no purpose* outside of achieving a more ideal syntax elsewhere. Its inclusion is hard to comprehend for anyone looking at the public facing API, as the type itself is decoupled from its actual purpose. SwiftUI removed `StaticMember` before exiting beta for exactly that reason: developers were commonly confused by its existence, declaration complexity, and usage within the framework.
@@ -164,24 +169,33 @@ The second option is a much better choice that avoids having to do a global look
164169
This approach works well for references without an explicit base, let’s consider an example:
165170

166171
```swift
167-
protocol ToggleStyle {
168-
}
172+
// Existing SwiftUI APIs:
173+
174+
public protocol ToggleStyle { ... }
169175

170-
struct SwitchToggleStyle: ToggleStyle {
176+
public struct DefaultToggleStyle: ToggleStyle { ... }
177+
public struct SwitchToggleStyle: ToggleStyle { ... }
178+
public struct CheckboxToggleStyle: ToggleStyle { ... }
179+
180+
extension View {
181+
public func toggleStyle<S: ToggleStyle>(_ style: S) -> some View
171182
}
172183

184+
// Possible SwiftUI APIs:
185+
173186
extension ToggleStyle {
174-
static var switch: SwitchToggleStyle { SwitchToggleStyle() }
187+
public static var `default`: DefaultToggleStyle { get }
188+
public static var `switch`: SwitchToggleStyle { get }
189+
public static var checkbox: CheckboxToggleStyle { get }
175190
}
176191

177-
func applyStyle<S: ToggleStyle>(_: S) {
178-
// ...
179-
}
192+
// Leading dot syntax (using proposed solution):
180193

181-
applyStyle(.switch)
194+
Toggle("Wi-Fi", isOn: $isWiFiEnabled)
195+
.toggleStyle(.switch)
182196
```
183197

184-
In this case (`applyStyle(.switch)`) the reference to the member `.switch` is re-written to be `SwitchToggleStyle.switch` in the type-checked AST.
198+
In the case of `.toggleStyle(.switch)`, the reference to the member `.switch` is re-written to be `SwitchToggleStyle.switch` in the type-checked AST.
185199

186200
To make this work the type-checker would attempt to infer protocol conformance requirements from context, e.g. the call site of a generic function (in this case there is only one such requirement - the protocol `ToggleStyle`), and propagate them to the type variable representing the implicit base type of the chain. If there is no other contextual information available, e.g. the result type couldn’t be inferred to some concrete type, the type-checker would attempt to bind base to the type of the inferred protocol requirement.
187201

0 commit comments

Comments
 (0)