Skip to content

[Macros] Rework the ExpressionMacro API based on pitch feedback #1104

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
merged 10 commits into from
Dec 3, 2022

Conversation

DougGregor
Copy link
Member

Make a number of changes to the API for expression macros:

  • MacroEvaluationContext gets renamed to MacroExpansionContext
  • Remove the source location converter from MacroExpansionContext, because one shouldn't have access to the whole source file
  • Detach a macro expansion from its parent nodes, because one shouldn't have access to the whole source file
  • Pass MacroExpansionContext inout
  • Remove MacroResult; instead, allow diagnostics to be emitted via the macro expansion context
  • Add a simplistic MacroExpansionContext.createUniqueLocalName()
  • Rename ExpressionMacro.apply to ExpressionMacro.expand

…text.

Having the source location converter in the context exposes the entire
contents of the source file containing the macro expansion to the
implementation of the macro. While convenient for the macro author,
this breaks Swift's incremental build model, because Swift assumes
that (e.g.) changing the body of a function cannot affect the result of
type-checking the body of an unrelated function.

Drop the implementations of some "built-in" macros that are no longer
expressible, such as `#filePath`, `#line`, and `#column`.
We're talking about these as macro "expansions" uniformly, now.
This matches the current proposal, and makes it possible for mutations
to the context in the future.
Providing the macro expansion syntax node directly to the macro
implementation allowed those implementations to chase its parent
pointer, which indirectly exposed the full source code of the enclosing
file to the macro implementation. "Disconnect" the syntax node from
its parent so the syntax node is independent of all other source code
in the file.

Another sample macro implementation, `#function`, is now
unusable---but this is a better model for incremental builds.
Per pitch feedback, eliminate MacroResult. Instead, macro
implementations can produce diagnostics by calling `diagnose()` on the
macro evaluation context.
"Expand" better describes what the macro implementation is doing.
@DougGregor DougGregor requested a review from ahoppen as a code owner December 2, 2022 22:53
static func apply(
_ macro: MacroExpansionExprSyntax, in context: MacroEvaluationContext
) -> MacroResult<ExprSyntax>
static func expand(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO the method should start with a noun phrase to be in line with the API guidelines, e.g. expansion(for:in:), because the method is not meant to have side effects.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A later commit introduces the potential for side effects in the macro evaluation context, e.g., for emitting diagnostics and creating new unique local names.

Copy link
Member Author

@DougGregor DougGregor Dec 5, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've thought about this more, and you're totally right. PR to call it expansion(for:in:): #1112

@DougGregor
Copy link
Member Author

swiftlang/swift#62381

@swift-ci please test

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