Skip to content

Commit 07803d5

Browse files
committed
Refocus all examples around ToggleStyle
1 parent b86fd54 commit 07803d5

File tree

1 file changed

+20
-15
lines changed

1 file changed

+20
-15
lines changed

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

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ which accepts instances of the `ToggleStyle` protocol, e.g.
7777
```swift
7878
public protocol ToggleStyle {
7979
associatedtype Body: View
80-
func makeBody(configuration: Configuration) -> some View
80+
func makeBody(configuration: Configuration) -> Body
8181
}
8282

8383
public struct DefaultToggleStyle: ToggleStyle { ... }
@@ -113,22 +113,27 @@ 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 {
117+
// ...
118+
typealias Member = StaticMember<Self>
119+
}
120+
116121
struct StaticMember<Base> {
117122
var base: Base
118123
init(_ base: Base)
119124
}
120125

121-
extension StaticMember where Base: ColorStyle {
122-
static var red: StaticMember<RedStyle> { .init(.init()) }
123-
static var blue: StaticMember<BlueStyle> { .init(.init()) }
126+
extension StaticMember where Base: ToggleStyle {
127+
static var switch: StaticMember<SwitchToggleStyle> { .init(.init()) }
128+
static var checkbox: StaticMember<CheckboxToggleStyle> { .init(.init()) }
124129
}
125130

126131
extension View {
127-
func colorStyle<S : ColorStyle>(_ style: S.Member) -> some View
132+
func toggleStyle<S : ToggleStyle>(_ style: S.Member) -> some View
128133
}
129134

130-
MyView().colorStyle(.red)
131-
MyView().colorStyle(.blue)
135+
MyView().toggleStyle(.switch)
136+
MyView().toggleStyle(.checkbox)
132137
```
133138

134139
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.
@@ -159,27 +164,27 @@ The second option is a much better choice that avoids having to do a global look
159164
This approach works well for references without an explicit base, let’s consider an example:
160165

161166
```swift
162-
protocol Style {
167+
protocol ToggleStyle {
163168
}
164169

165-
struct BorderedStyle : Style {
170+
struct SwitchToggleStyle: ToggleStyle {
166171
}
167172

168-
extension Style {
169-
static var bordered: BorderedStyle { BorderedStyle() }
173+
extension ToggleStyle {
174+
static var switch: SwitchToggleStyle { SwitchToggleStyle() }
170175
}
171176

172-
func applyStyle<S: Style>(_: S) {
177+
func applyStyle<S: ToggleStyle>(_: S) {
173178
// ...
174179
}
175180

176-
applyStyle(.bordered)
181+
applyStyle(.switch)
177182
```
178183

179184

180-
In this case (`applyStyle(.bordered)`) the reference to the member `.bordered` is re-written to be `Bordered.bordered` in the type-checked AST.
185+
In this case (`applyStyle(.switch)`) the reference to the member `.switch` is re-written to be `SwitchToggleStyle.switch` in the type-checked AST.
181186

182-
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 `Style`), 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.
187+
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.
183188

184189
Member lookup filtering is adjusted to find static members on protocol metatype base but the `Self` part of the reference type is replaced with result type of the discovered member (looking through function types and IUOs) and additional conformance requirements are placed on it (the new `Self` type) to make sure that the new base does conform to the expected protocol.
185190

0 commit comments

Comments
 (0)