Skip to content
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

[509] Add conformingTo parameter to MemberMacro.expansion function #2420

Merged

Conversation

ahoppen
Copy link
Collaborator

@ahoppen ahoppen commented Jan 9, 2024

DougGregor and others added 2 commits January 8, 2024 15:39
… operation

Stage in an entrypoint for member macros that allows them to learn
about which conformances that they've asked about are "missing",
meaning that they are not present on the type (ignoring those that
would be generated by an extension macro). This information is
equivalent to the information provided to extension macros, although
the member macro itself cannot create the conformance.
…ansion` method

When adding a new type that conforms to `MemberMacro`, no `expansion` function is required to be implemented. It’s necessary to do it this way because:

- `expansion(of:providingMembersOf:in:)` needs to exist as a protocol requirement to keep Swift 5.9 macros that implement this method compiling
- `expansion(of:providingMembersOf:in:)` needs to be defaulted so that macros implementing `expansion(of:providingMembersOf:conformingTo:in:)` don’t need to also provide an implementation for the legacy version that doesn’t have `conformingTo:`
- `expansion(of:providingMembersOf:conformingTo:in:)` obviously needs to exist since it’s the new dedicated entry point
- `expansion(of:providingMembersOf:conformingTo:in:)` needs to have a default implementation that calls `expansion(of:providingMembersOf:in:)` so that 5.9 macros continue to work
- We can’t mark `expansion(of:providingMembersOf:in:)` as deprecated because it’s called by the default implementation of `expansion(of:providingMembersOf:conformingTo:in:)` and we want to keep swift-syntax building without warnings.

At the moment, we provide default implementations for both `expansion` functions that call each other, which causes an infinite recursion, that makes it non-obvious to see what’s going wrong.

With this change, the default implementation of the legacy `expansion(of:providingMembersOf:in:)` method throws an error saying that you need to implement either of the two expansion methods. That way you get the following behavior:
- If you don’t implement either expansion function, the error gets thrown
- If a macro implements the legacy `expansion(of:providingMembersOf:in:)` function, then it overrides the throwing version and the macro works.
- If a macro implements the new `expansion(of:providingMembersOf:conformingTo:in:)` method, then the compiler calls into that method directly and the legacy `expansion(of:providingMembersOf:in:)` never gets invoked by the compiler.

The only possible issue I can think of is if a library is calling `expansion(of:providingMembersOf:in:)` but the macro only implements `expansion(of:providingMembersOf:conformingTo:in:)`. In this case an error would get thrown where it currently isn’t. But since I don’t see any reason why anyone would be calling `expansion(of:providingMembersOf:in:)` directly, I think this is fine.
@ahoppen
Copy link
Collaborator Author

ahoppen commented Jan 9, 2024

✅ Testing suceeded

@ahoppen ahoppen merged commit 43c802f into apple:package-release/509 Jan 9, 2024
@ahoppen ahoppen deleted the ahoppen/509/conforming-to branch January 9, 2024 00:18
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.

None yet

3 participants