Skip to content

Commit 5cdd34a

Browse files
authored
Merge pull request swiftlang#66198 from DougGregor/closure-local-discriminators-in-macro-expansions
[Macros] Rework the way we assign closure and local discriminators
2 parents 1dfd8d6 + 7386a7e commit 5cdd34a

File tree

6 files changed

+66
-21
lines changed

6 files changed

+66
-21
lines changed

include/swift/AST/ASTContext.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -342,10 +342,6 @@ class ASTContext final {
342342
/// The # of times we have performed typo correction.
343343
unsigned NumTypoCorrections = 0;
344344

345-
/// The next auto-closure discriminator. This needs to be preserved
346-
/// across invocations of both the parser and the type-checker.
347-
unsigned NextAutoClosureDiscriminator = 0;
348-
349345
/// Cached mapping from types to their associated tangent spaces.
350346
llvm::DenseMap<Type, Optional<TangentSpace>> AutoDiffTangentSpaces;
351347

@@ -1121,6 +1117,13 @@ class ASTContext final {
11211117
unsigned getNextMacroDiscriminator(MacroDiscriminatorContext context,
11221118
DeclBaseName baseName);
11231119

1120+
/// Get the next discriminator within the given declaration context.
1121+
unsigned getNextDiscriminator(const DeclContext *dc);
1122+
1123+
/// Set the maximum assigned discriminator within the given declaration context.
1124+
void setMaxAssignedDiscriminator(
1125+
const DeclContext *dc, unsigned discriminator);
1126+
11241127
/// Retrieve the Clang module loader for this ASTContext.
11251128
///
11261129
/// If there is no Clang module loader, returns a null pointer.

lib/AST/ASTContext.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,9 @@ struct ASTContext::Implementation {
403403
llvm::DenseMap<std::pair<const void *, Identifier>, unsigned>
404404
NextMacroDiscriminator;
405405

406+
/// Local and closure discriminators per context.
407+
llvm::DenseMap<const DeclContext *, unsigned> NextDiscriminator;
408+
406409
/// Structure that captures data that is segregated into different
407410
/// arenas.
408411
struct Arena {
@@ -2185,6 +2188,18 @@ unsigned ASTContext::getNextMacroDiscriminator(
21852188
return getImpl().NextMacroDiscriminator[key]++;
21862189
}
21872190

2191+
/// Get the next discriminator within the given declaration context.
2192+
unsigned ASTContext::getNextDiscriminator(const DeclContext *dc) {
2193+
return getImpl().NextDiscriminator[dc];
2194+
}
2195+
2196+
/// Set the maximum assigned discriminator within the given declaration context.
2197+
void ASTContext::setMaxAssignedDiscriminator(
2198+
const DeclContext *dc, unsigned discriminator) {
2199+
assert(discriminator >= getImpl().NextDiscriminator[dc]);
2200+
getImpl().NextDiscriminator[dc] = discriminator;
2201+
}
2202+
21882203
void ASTContext::verifyAllLoadedModules() const {
21892204
#ifndef NDEBUG
21902205
FrontendStatsTracer tracer(Stats, "verify-all-loaded-modules");

lib/AST/Decl.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2934,10 +2934,26 @@ unsigned ValueDecl::getLocalDiscriminator() const {
29342934
return 0;
29352935

29362936
// Assign local discriminators in this context.
2937+
ASTContext &ctx = getASTContext();
29372938
evaluateOrDefault(
2938-
getASTContext().evaluator,
2939+
ctx.evaluator,
29392940
LocalDiscriminatorsRequest{getDeclContext()}, InvalidDiscriminator);
29402941

2942+
// If we don't have a discriminator, and either
2943+
// 1. We have ill-formed code and we're able to assign a discriminator, or
2944+
// 2. We are in a macro expansion buffer
2945+
//
2946+
// then assign the next discriminator now.
2947+
if (LocalDiscriminator == InvalidDiscriminator &&
2948+
(ctx.Diags.hadAnyError() ||
2949+
(getLoc().isValid() &&
2950+
getModuleContext()->getSourceFileContainingLocation(getLoc())
2951+
->getFulfilledMacroRole() != None))) {
2952+
auto discriminator = ctx.getNextDiscriminator(getDeclContext());
2953+
ctx.setMaxAssignedDiscriminator(getDeclContext(), discriminator + 1);
2954+
const_cast<ValueDecl *>(this)->LocalDiscriminator = discriminator;
2955+
}
2956+
29412957
assert(LocalDiscriminator != InvalidDiscriminator);
29422958

29432959
return LocalDiscriminator;

lib/AST/Expr.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1901,16 +1901,22 @@ unsigned AbstractClosureExpr::getDiscriminator() const {
19011901
if (raw != InvalidDiscriminator)
19021902
return raw;
19031903

1904+
ASTContext &ctx = getASTContext();
19041905
evaluateOrDefault(
1905-
getASTContext().evaluator, LocalDiscriminatorsRequest{getParent()}, 0);
1906+
ctx.evaluator, LocalDiscriminatorsRequest{getParent()}, 0);
19061907

1907-
// Ill-formed code might not be able to assign discriminators, so assign
1908-
// a new one now.
1908+
// If we don't have a discriminator, and either
1909+
// 1. We have ill-formed code and we're able to assign a discriminator, or
1910+
// 2. We are in a macro expansion buffer
1911+
//
1912+
// then assign the next discriminator now.
19091913
if (getRawDiscriminator() == InvalidDiscriminator &&
1910-
getASTContext().Diags.hadAnyError()) {
1914+
(ctx.Diags.hadAnyError() ||
1915+
getParentSourceFile()->getFulfilledMacroRole() != None)) {
1916+
auto discriminator = ctx.getNextDiscriminator(getParent());
1917+
ctx.setMaxAssignedDiscriminator(getParent(), discriminator + 1);
19111918
const_cast<AbstractClosureExpr *>(this)->
1912-
Bits.AbstractClosureExpr.Discriminator =
1913-
getASTContext().NextAutoClosureDiscriminator++;
1919+
Bits.AbstractClosureExpr.Discriminator = discriminator;
19141920
}
19151921

19161922
assert(getRawDiscriminator() != InvalidDiscriminator);

lib/Sema/TypeCheckStmt.cpp

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ namespace {
255255
}
256256

257257
MacroWalking getMacroWalkingBehavior() const override {
258-
return MacroWalking::ArgumentsAndExpansion;
258+
return MacroWalking::Arguments;
259259
}
260260

261261
PreWalkResult<Expr *> walkToExprPre(Expr *E) override {
@@ -410,7 +410,6 @@ unsigned LocalDiscriminatorsRequest::evaluate(
410410
LocalDiscriminatorsRequest{dc->getParent()}, 0);
411411
}
412412

413-
Optional<unsigned> expectedNextAutoclosureDiscriminator = None;
414413
ASTNode node;
415414
ParameterList *params = nullptr;
416415
ParamDecl *selfParam = nullptr;
@@ -436,7 +435,7 @@ unsigned LocalDiscriminatorsRequest::evaluate(
436435
params = closure->getParameters();
437436
} else if (auto topLevel = dyn_cast<TopLevelCodeDecl>(dc)) {
438437
node = topLevel->getBody();
439-
expectedNextAutoclosureDiscriminator = ctx.NextAutoClosureDiscriminator;
438+
dc = topLevel->getParentModule();
440439
} else if (auto patternBindingInit = dyn_cast<PatternBindingInitializer>(dc)){
441440
auto patternBinding = patternBindingInit->getBinding();
442441
node = patternBinding->getInit(patternBindingInit->getBindingIndex());
@@ -472,12 +471,11 @@ unsigned LocalDiscriminatorsRequest::evaluate(
472471
params = getParameterList(dc);
473472
}
474473

474+
auto startDiscriminator = ctx.getNextDiscriminator(dc);
475475
if (!node && !params && !selfParam)
476-
return 0;
476+
return startDiscriminator;
477477

478-
SetLocalDiscriminators visitor(
479-
expectedNextAutoclosureDiscriminator.value_or(0)
480-
);
478+
SetLocalDiscriminators visitor(startDiscriminator);
481479

482480
// Set local discriminator for the 'self' parameter.
483481
if (selfParam)
@@ -494,9 +492,7 @@ unsigned LocalDiscriminatorsRequest::evaluate(
494492
node.walk(visitor);
495493

496494
unsigned nextDiscriminator = visitor.maxAssignedDiscriminator();
497-
if (expectedNextAutoclosureDiscriminator) {
498-
ctx.NextAutoClosureDiscriminator = nextDiscriminator;
499-
}
495+
ctx.setMaxAssignedDiscriminator(dc, nextDiscriminator);
500496

501497
// Return the next discriminator.
502498
return nextDiscriminator;

test/Macros/macro_expand.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,3 +400,12 @@ func testFreestandingWithClosure(i: Int) {
400400
return x
401401
}
402402
}
403+
404+
// Nested macros with closures
405+
@freestanding(expression) macro coerceToInt<T>(_ value: T) -> Int = #externalMacro(module: "MacroDefinition", type: "CoerceToIntMacro")
406+
407+
func testFreestandingClosureNesting() {
408+
_ = #stringify({ () -> Int in
409+
#coerceToInt(2)
410+
})
411+
}

0 commit comments

Comments
 (0)