Skip to content

[Macros] Fix visiting nested conformance macro declarations in SIL and IRGen. #65231

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 1 commit into from
Apr 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions lib/IRGen/GenDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5501,6 +5501,11 @@ void IRGenModule::emitNestedTypeDecls(DeclRange members) {
continue;

member->visitAuxiliaryDecls([&](Decl *decl) {
// FIXME: Conformance macros can generate extension decls. These
// are visited as top-level decls; skip them here.
if (isa<ExtensionDecl>(decl))
return;

emitNestedTypeDecls({decl, nullptr});
});
switch (member->getKind()) {
Expand Down
32 changes: 32 additions & 0 deletions lib/SILGen/SILGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2196,6 +2196,10 @@ class SILGenModuleRAII {
for (auto *D : sf->getTopLevelDecls()) {
// Emit auxiliary decls.
D->visitAuxiliaryDecls([&](Decl *auxiliaryDecl) {
// Skip extensions decls; they are visited below.
if (isa<ExtensionDecl>(auxiliaryDecl))
return;

FrontendStatsTracer StatsTracer(SGM.getASTContext().Stats,
"SILgen-decl", auxiliaryDecl);
SGM.visit(auxiliaryDecl);
Expand All @@ -2206,6 +2210,34 @@ class SILGenModuleRAII {
SGM.visit(D);
}

// FIXME: Visit macro-generated extensions separately.
//
// The code below that visits auxiliary decls of the top-level
// decls in the source file does not work for nested types with
// attached conformance macros:
// ```
// struct Outer {
// @AddConformance struct Inner {}
// }
// ```
// Because the attached-to decl is not at the top-level. To fix this,
// visit the macro-generated conformances that are recorded in the
// synthesized file unit to cover all macro-generated extension decls.
if (auto *synthesizedFile = sf->getSynthesizedFile()) {
for (auto *D : synthesizedFile->getTopLevelDecls()) {
if (!isa<ExtensionDecl>(D))
continue;

auto *sf = D->getInnermostDeclContext()->getParentSourceFile();
if (sf->getFulfilledMacroRole() != MacroRole::Conformance)
continue;

FrontendStatsTracer StatsTracer(SGM.getASTContext().Stats,
"SILgen-decl", D);
SGM.visit(D);
}
}

for (Decl *D : sf->getHoistedDecls()) {
FrontendStatsTracer StatsTracer(SGM.getASTContext().Stats,
"SILgen-decl", D);
Expand Down
5 changes: 5 additions & 0 deletions lib/SILGen/SILGenType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1086,6 +1086,11 @@ class SILGenType : public TypeMemberVisitor<SILGenType> {
SGM.emitLazyConformancesForType(theType);

forEachMemberToLower(theType, [&](Decl *member) {
// FIXME: Conformance macros can generate extension decls. These
// are visited as top-level decls; skip them here.
if (isa<ExtensionDecl>(member))
return;

visit(member);
});

Expand Down
6 changes: 6 additions & 0 deletions test/Macros/macro_expand_conformances.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ struct S {}
@Hashable
struct S2 {}

enum E {
@Equatable struct Nested {}
}

// CHECK-DUMP: @__swiftmacro_25macro_expand_conformances1S9EquatablefMc_.swift
// CHECK-DUMP: extension S : Equatable {}

Expand All @@ -38,6 +42,8 @@ requireEquatable(S())
requireEquatable(S2())
requireHashable(S2())

requireEquatable(E.Nested())

@attached(conformance)
@attached(member, names: named(requirement))
macro DelegatedConformance() = #externalMacro(module: "MacroDefinition", type: "DelegatedConformanceMacro")
Expand Down