Skip to content

[5.9] Arbitrary peer and freestanding macros #65127

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

Conversation

DougGregor
Copy link
Member

  • Explanation: Rework the point at which macros are expanded for name-lookup purposes in two key ways. First, ensure that we expand peer and freestanding macros that introduce "arbitrary" names whenever we are performing lookup into the corresponding scope, but with one critical heuristic: the arguments of macros expansions themselves do not see the results of macro expansions. Second, rework the mangling scheme used for attached macros to use context + declaration name + macro name + discriminator, eliminating the dependency on the interface type. In both cases, the complexity is in avoiding reference cycles detected by the request-evaluator, by ensuring that the process of expanding a macro (and deciding which macro to expand) does not depend on the expansion of other macros.
  • Scope: Affects code using macros, especially in the areas of name mangling and name lookup.
  • Risk: Low; only affects macros, although it is a significant change to macro mangling and expands "arbitrary" macros much more freely.
  • Issue: rdar://107596329, rdar://107442606
  • Testing: Additional tests added.
  • Original pull request: [Module-scope lookup] Only add macro-expanded names that match. #64967, [Module-scope lookup] Find arbitrary names in macro expansions. #64968, [Macros] Mangle attached macro expansions based only on syntactic information #65032

When we look into expanded macros to find declarations for module-scope
name lookup, make sure that we only return declarations whose name
matches the requested name.

We were effectively spamming the results with unrelated names, and
most clients trust the results of this lookup (vs. filtering them
further), so they would get confused. The particular failure for this
test is that type reconstruction would fail because we were looking
for one unique name, but we found many non-matching names, and type
reconstruction bails out rather than try to filter further.

(cherry picked from commit 8e63bf1)
…ments.

Macros introduced a significant wrinkle into Swift's name lookup mechanism.
Specifically, when resolving names (and, really, anything else) within the
arguments to a macro expansion, name lookup must not try to expand any
macros, because doing so trivially creates a cyclic dependency amongst the
macro expansions that will be detected by the request-evaluator.

Our lookup requests don't always have enough information to answer the
question "is this part of an argument to a macro?", so we do a much simpler,
more efficient, and not-entirely-sound hack based on the request-evaluator.
Specifically, if we are in the process of resolving a macro (which is
determined by checking for the presence of a `ResolveMacroRequest` in the
request-evaluator stack), then we adjust the options used for the name
lookup request we are forming to exclude macro expansions. The evaluation
of that request will then avoid expanding any macros, and not produce any
results that involve entries in already-expanded macros. By adjusting the
request itself, we still distinguish between requests that can and cannot
look into macro expansions, so it doesn't break caching for those immediate
requests.

Over time, we should seek to replace this heuristic with a location-based
check, where we use ASTScope to determine whether we are inside a macro
argument. This existing check might still be useful because it's going to
be faster than a location-based query, but the location-based query can be
fully correct.

This addresses a class of cyclic dependencies that we've been seeing
with macros, and aligns the lookup behavior for module-level lookups
with that specified in the macros proposals. It is not fully complete
because lookup until nominal types does not yet support excluding
results from macro expansions.

(cherry picked from commit f96240d)
Whenever we perform a name lookup, we need to make sure to expand
all macros that use `names: arbitrary`, because of course they can
produce... wait for it... arbitrary names, and we don't know what they
are until we instatiate them.

(cherry picked from commit bbe4ff1)
…ypes/extensions

Eliminate a source of cyclic dependencies by not expanding macros when
we are resolving macro arguments within a type or extension context.
This extends the scheme introduced for module-scope lookup to also
apply to lookup within types.

(cherry picked from commit 527a4cd)
…ormation

The mangling of attached macro expansions based on the declaration to
which they are attached requires semantic information (specifically,
the interface type of that declaration) that caused cyclic
dependencies during type checking. Replace the mangling with a
less-complete mangling that only requires syntactic information from
the declaration, i.e., the name of the declaration to which the macro
was attached.

This eliminates reference cycles that occur with attached macros that
produce arbitrary names.

(cherry picked from commit a23d39b)
…ssors

Adding accessors to a stored property, which removes its initializer.
Force computation of the interface type first.

There are better ways to model this in the AST, but it requires
reworking how we handle initializers to break them into requests.

(cherry picked from commit ef7970b)
(cherry picked from commit 097ecfd)
(cherry picked from commit fb82b8f)
@DougGregor DougGregor requested a review from a team as a code owner April 13, 2023 02:02
@DougGregor
Copy link
Member Author

@swift-ci please test

@DougGregor DougGregor merged commit 727bccd into swiftlang:release/5.9 Apr 13, 2023
@DougGregor DougGregor deleted the arbitrary-peer-and-freestanding-macros-5.9 branch April 13, 2023 10:46
@AnthonyLatsis AnthonyLatsis added the 🍒 release cherry pick Flag: Release branch cherry picks label May 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🍒 release cherry pick Flag: Release branch cherry picks
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants