Skip to content

Commit 82bc829

Browse files
committed
[Macros] Don't visit macro-generated extensions in 'visitAuxiliaryDecls'.
Macro-generated extensions are hoisted to file scope, because extensions are not valid in nested scopes. Callers of 'visitAuxiliaryDecls' assume that the auxiliary decls are in the same decl context as the original, which is clearly not the case for extensions, and it leads to issues like visiting extension at the wrong time during SILGen. The extensions are already added to the top-level decls, so we don't need to visit them as auxiliary decls as long as we type check them eagerly after expansion.
1 parent 3676379 commit 82bc829

File tree

4 files changed

+16
-19
lines changed

4 files changed

+16
-19
lines changed

lib/AST/Decl.cpp

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -407,20 +407,6 @@ void Decl::visitAuxiliaryDecls(
407407
}
408408
}
409409

410-
if (auto *nominal = dyn_cast<NominalTypeDecl>(mutableThis)) {
411-
auto conformanceBuffers =
412-
evaluateOrDefault(ctx.evaluator,
413-
ExpandConformanceMacros{nominal},
414-
{});
415-
for (auto bufferID : conformanceBuffers) {
416-
auto startLoc = sourceMgr.getLocForBufferStart(bufferID);
417-
auto *sourceFile = moduleDecl->getSourceFileContainingLocation(startLoc);
418-
for (auto *extension : sourceFile->getTopLevelDecls()) {
419-
callback(extension);
420-
}
421-
}
422-
}
423-
424410
if (visitFreestandingExpanded) {
425411
if (auto *med = dyn_cast<MacroExpansionDecl>(mutableThis)) {
426412
if (auto bufferID = evaluateOrDefault(

lib/SILGen/SILGenType.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,11 +1101,6 @@ class SILGenType : public TypeMemberVisitor<SILGenType> {
11011101
SGM.emitLazyConformancesForType(theType);
11021102

11031103
forEachMemberToLower(theType, [&](Decl *member) {
1104-
// FIXME: Conformance macros can generate extension decls. These
1105-
// are visited as top-level decls; skip them here.
1106-
if (isa<ExtensionDecl>(member))
1107-
return;
1108-
11091104
visit(member);
11101105
});
11111106

lib/Sema/TypeCheckMacros.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1446,6 +1446,16 @@ swift::expandConformances(CustomAttr *attr, MacroDecl *macro,
14461446
if (auto file = dyn_cast<FileUnit>(
14471447
decl->getDeclContext()->getModuleScopeContext()))
14481448
file->getOrCreateSynthesizedFile().addTopLevelDecl(extension);
1449+
1450+
// Most other macro-generated declarations are visited and type-checked
1451+
// through calling 'visitAuxiliaryDecls' on the original declaration the
1452+
// macro is attached to. We don't do this for macro-generated extensions,
1453+
// because the extension is not a peer of the original declaration. Instead
1454+
// of requiring all callers of 'visitAuxiliarDecls' to understsand the
1455+
// hoisting behavior of macro-generated extensions, we simply expose the
1456+
// extension to 'getTopLevelDecls()' and type check the extension eagerly
1457+
// here.
1458+
TypeChecker::typeCheckDecl(extension);
14491459
}
14501460

14511461
return macroSourceFile->getBufferID();

test/Macros/macro_expand_conformances.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,12 @@ requireHashable(S2())
6363

6464
requireEquatable(E.Nested())
6565

66+
extension E {
67+
@Equatable struct NestedInExtension {}
68+
}
69+
70+
requireEquatable(E.NestedInExtension())
71+
6672
#if TEST_DIAGNOSTICS
6773
requireEquatable(PublicEquatable())
6874

0 commit comments

Comments
 (0)