Skip to content

[SE-0407] [Macros] Provide member macros with information about "missing" conformances #68372

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

DougGregor
Copy link
Member

@DougGregor DougGregor commented Sep 7, 2023

Provide member macros with similar information about conformances to what extension macros receive, allowing member macros to document which conformances they care about (e.g., Decodable) and then receiving the list of conformances that aren't already available for the type in question. For example, a macro such as

@attached(member, conformances: Decodable, Encodable, names: named(init(from:), encode(to:)))
macro Codable() = ...

Expanded on a type that is not already Decodable/Encodable would be provided with Decodable and Encodable (via the new missingConformancesTo: argument to the macro implementation) when the type itself does not conform to those types.

Member macros still cannot produce conformances, so this is likely to be used in conjunction with extension macros most of the time. The extension macro declares the conformance, and can also declare any members that shouldn't be part of the primary type definition---such as initializers that shouldn't suppress the memberwise initializer. On the other hand, the member macro will need to define any members that must be in the primary definition, such as required initializers, members that must be overridable by subclasses, and stored properties.

Codable synthesis is an example that benefits from member macros with conformances, because for classes it wants to introduce a required initializer for decoding and an overridable encode operation, and these must be members of the nominal type itself. Specifically, the Codable macro above is likely to have two attached member roles:

@attached(member, conformances: Decodable, Encodable, names: named(init(from:), encode(to:)))
@attached(extension, conformances: Decodable, Encodable, names: named(init(from:), encode(to:)))
macro Codable() = ...

where the "extension" role is responsible for defining the conformance (always), and the "member" creates the appropriate members for classes (init vs. required init).

Tracked by rdar://112532829. Cherry-picked from #67758

@DougGregor DougGregor requested a review from a team as a code owner September 7, 2023 14:01
…ormances

Provide member macros with similar information about conformances to
what extension macros receive, allowing member macros to document
which conformances they care about (e.g., Decodable) and then
receiving the list of conformances that aren't already available for
the type in question. For example, a macro such as

    @attached(member, conformances: Decodable, Encodable, names:
named(init(from:), encode(to:)))
    macro Codable() = ...

Expanded on a type that is not already Decodable/Encodable would be
provided with Decodable and Encodable (via the new
`missingConformancesTo:` argument to the macro implementation) when
the type itself does not conform to those types.

Member macros still cannot produce conformances, so this is likely to
be used in conjunction with extension macros most of the time. The
extension macro declares the conformance, and can also declare any
members that shouldn't be part of the primary type definition---such
as initializers that shouldn't suppress the memberwise initializer. On
the other hand, the member macro will need to define any members that
must be in the primary definition, such as required initializers,
members that must be overridable by subclasses, and stored properties.

Codable synthesis is an example that benefits from member macros with
conformances, because for classes it wants to introduce a required
initializer for decoding and an overridable encode operation, and
these must be members of the nominal type itself. Specifically, the
`Codable` macro above is likely to have two attached member roles:

    @attached(member, conformances: Decodable, Encodable, names:
named(init(from:), encode(to:)))
    @attached(extension, conformances: Decodable, Encodable, names:
named(init(from:), encode(to:)))
    macro Codable() = ...

where the "extension" role is responsible for defining the conformance
(always), and the "member" creates the appropriate members for classes
(`init` vs. `required init`).

Tracked by rdar://112532829.
@DougGregor DougGregor force-pushed the member-macro-conformances-5.9 branch from e0facd2 to 61a975c Compare September 7, 2023 15:25
@DougGregor
Copy link
Member Author

swiftlang/swift-syntax#2164

@swift-ci please test

@DougGregor
Copy link
Member Author

swiftlang/swift-syntax#2164

@swift-ci please test Windows

@DougGregor
Copy link
Member Author

@swift-ci please test Windows

@DougGregor DougGregor merged commit 7d181c1 into swiftlang:release/5.9 Sep 7, 2023
@DougGregor DougGregor deleted the member-macro-conformances-5.9 branch September 7, 2023 23:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants