You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When either of these protocols are attached to a given type, the compiler synthesizes the protocol's requirements in the type its attached to. Not only that, but the compiler performs validation of the type to ensure that each of its stored members conform to the protocol which is required for being able to automatically synthesize the conformance. If the requirements can't be automatically synthesized, the requirements can be manually implemented on the type. Not only that but the protocol's requirements can be manually implemented even if the requirements could be synthesized by the compiler.
110
110
111
-
This kind of functionality can already be somewhat emulated using the 'conformance' field on the `member` or `extension` attached macro type. For example, we could create an attached member macro that conforms the attached type to the `Encodable` protocol and synthesizes the requirements of the protocol:
111
+
This kind of functionality can already be somewhat emulated using the 'conformance' field on the `member` or `extension` attached macro type. For example, we could create an attached member macro that conforms the attached type to a given protocol and synthesizes the requirements of the protocol:
This kind of functionality would be incredibly useful for
153
+
Although this works fine, it does lack some of the functionality that makes these kinds of protocols what they are today. Specifically, if one directly conforms to a given protocol (e.g. `FooBar`) then the protocol's requirements aren't automatically synthesized like they would have been had the macro been used intstead:
135
154
136
-
While this attached macro type would certainly be useful for more complex protocols with multiple required members where we wanted to synthesize each of the members, creating a macro for each of the protocol's members would become quite cumbersome and polute the global namespace with a number of different single-use macros. It we were to instead create a single attached macro that we would attach to each of the different declarations we want to synthesize, the implementation of the macro could become exceeding complex to account for all of the different members that it's supposed to generate, assuming that we could even structure a macro in this way.
155
+
```swift
156
+
structFooBarImplA: FooBar {
157
+
// error: Missing implementations for `foo()` and `bar()`
158
+
}
159
+
160
+
@FooBarMacro
161
+
structFooBarImplB {
137
162
138
-
Describe the problems that this proposal seeks to address. If the
139
-
problem is that some common pattern is currently hard to express, show
140
-
how one can currently get a similar effect and describe its
141
-
drawbacks. If it's completely new functionality that cannot be
142
-
emulated, motivate why this new functionality would help Swift
143
-
developers create better Swift code.
163
+
}
164
+
165
+
// Conformance to `FooBar` + requirements synthesized in an extension of `FooBarImplB`:
166
+
//
167
+
// extension FooBarImplB: FooBar {
168
+
// func foo() -> Self.Foo {
169
+
// ...
170
+
// }
171
+
// func bar() -> Self.Bar {
172
+
// ...
173
+
// }
174
+
// }
175
+
```
176
+
177
+
Furthermore, this workaround doesn't allow for the associated protocol to be composed into other protocols or types like the way that `Encodable` and `Decodable` are composed in the `Codable` typealias:
// error: Missing implementations for `foo()` and `bar()`
189
+
}
190
+
```
191
+
192
+
Because of these drawbacks we are proposing a new protocol attached macro type that mirrors the behavior of these kind of special protocols where the macro is invoked by conforming a type to the protocol.
144
193
145
194
## Proposed solution
146
195
147
-
Describe your solution to the problem. Provide examples and describe
148
-
how they work. Show how your solution is better than current
149
-
workarounds: is it cleaner, safer, or more efficient?
196
+
The proposed solution is to create a new attached macro type `conformance` whose usage is restricted to protocol declarations:
197
+
198
+
```swift
199
+
@attached(conformance, ...)
200
+
protocolFooBar {
201
+
...
202
+
}
203
+
```
204
+
205
+
The implementation of the macro would then be invoked whenever the protocol is formally adopted on a conrete type, that is to say adopted by a class, struct, enum, or actor. When added to the inheritance clause of another protocol, the macro wouldn't be invoked. However, any conformance to the new protocol on a conrete would invoke the macro for that conrete type. For example:
206
+
207
+
```swift
208
+
@attached(conformance, ...)
209
+
protocolFoo {
210
+
associatedtypeFoo
211
+
funcfoo() -> Foo
212
+
}
213
+
214
+
// `Foo`'s macro isn't invoked here
215
+
protocolFooBar: Foo {
216
+
associatedtypeBar
217
+
funcbar() -> Bar
218
+
}
150
219
151
-
This section doesn't have to be comprehensive. Focus on the most
152
-
important parts of the proposal and make arguments about why the
153
-
proposal is better than the status quo.
220
+
// `Foo`'s macro is invoked here and synthesizes the `foo()` requirement.
221
+
structFooBarImpl: FooBar {
222
+
funcbar() ->Self.Bar {
223
+
...
224
+
}
225
+
}
226
+
```
154
227
155
228
## Detailed design
156
229
157
-
Describe the design of the solution in detail. If it involves new
158
-
syntax in the language, show the additions and changes to the Swift
159
-
grammar. If it's a new API, show the full API and its documentation
160
-
comments detailing what it does. The detail in this section should be
161
-
sufficient for someone who is *not* one of the authors to be able to
162
-
reasonably implement the feature.
230
+
The new `conformance` attached macro type would accept two different parameters in the attribute's usage:
231
+
232
+
1)`additionalMembers`
233
+
234
+
If provided, this field will accept a list of named parameters that specify any additional declarations that the macro will create. All of the declarations in the associated protocol are implicitly included and therefore it's not necessary to include them in this field. For example, if the `Encodable` protocol were declared as this kind of macro it would include an additional declaration for the `CodingKeys` enum that it creates:
The parameters of the required expansion function are defined as follows:
269
+
270
+
-`protocol`:
271
+
272
+
In lieu of providing an `AttributeSyntax` like is done in all other attached macros, this function accepts the declaration of the protocol that this macro is being invoked.
273
+
274
+
-`declaration`:
275
+
276
+
The `declaration` field is provided with the concrete declaration type that the protocol is attached to. The AST this declaration would be equivalent to the declaration that would be provided to the invocation of a `member` or `extension` macro. That is to say that the full AST of the conforming type would be provided, not just the type of the declaration or a "skeleton" of the declaration.
277
+
278
+
-`context`:
279
+
280
+
The standard macro expansion context included in all other macro expansion functions.
163
281
164
282
## Source compatibility
165
283
@@ -296,6 +414,8 @@ problem for many adopters of `@inlinable`.
296
414
297
415
## Alternatives considered
298
416
417
+
While this attached macro type would certainly be useful for more complex protocols with multiple required members where we wanted to synthesize each of the members, creating a macro for each of the protocol's members would become quite cumbersome and polute the global namespace with a number of different single-use macros. It we were to instead create a single attached macro that we would attach to each of the different declarations we want to synthesize, the implementation of the macro could become exceeding complex to account for all of the different members that it's supposed to generate, assuming that we could even structure a macro in this way.
418
+
299
419
Describe alternative approaches to addressing the same problem.
300
420
This is an important part of most proposal documents. Reviewers
301
421
are often familiar with other approaches prior to review and may
0 commit comments