Skip to content

Apply the @_alwaysEmitConformanceMetadata semantics to conformances originating from macro-expanded declarations and extensions #73680

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
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
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ class AlwaysEmitMetadataConformanceCollector : public ASTWalker {
AlwaysEmitMetadataConformanceDecls.push_back(ETD->getExtendedNominal());
}

// Visit peers expanded from macros
D->visitAuxiliaryDecls([&](Decl *decl) { decl->walk(*this); },
/*visitFreestandingExpanded=*/false);

return Action::Continue();
}
};
Expand All @@ -90,8 +94,12 @@ class AlwaysEmitConformanceMetadataPreservation : public SILModuleTransform {
for (const auto File : M.getSwiftModule()->getFiles())
File->getTopLevelDecls(TopLevelDecls);
} else {
for (const auto Primary : M.getSwiftModule()->getPrimarySourceFiles())
for (const auto Primary : M.getSwiftModule()->getPrimarySourceFiles()) {
Primary->getTopLevelDecls(TopLevelDecls);
// Visit macro expanded extensions
if (auto *synthesizedPrimary = Primary->getSynthesizedFile())
synthesizedPrimary->getTopLevelDecls(TopLevelDecls);
}
}
}
for (auto *TLD : TopLevelDecls)
Expand Down
77 changes: 77 additions & 0 deletions test/Reflection/Inputs/Macros.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import SwiftDiagnostics
import SwiftOperators
import SwiftSyntax
import SwiftSyntaxBuilder
import SwiftSyntaxMacros

public struct AddStructDeclMacro: DeclarationMacro {
public static func expansion(
of node: some FreestandingMacroExpansionSyntax,
in context: some MacroExpansionContext
) throws -> [DeclSyntax] {
return [
"""
struct MacroAddedStruct : TestEntity {}
"""
]
}
}

public struct AddPeerStructMacro: PeerMacro {
public static func expansion(
of node: AttributeSyntax,
providingPeersOf declaration: some DeclSyntaxProtocol,
in context: some MacroExpansionContext
) throws -> [DeclSyntax] {
let name = declaration.declName
return [
"""
struct _Peer_\(name) : TestEntity {}
"""
]
}
}

public struct AddExtensionMacro: ExtensionMacro {
public static func expansion(
of node: AttributeSyntax,
attachedTo declaration: some DeclGroupSyntax,
providingExtensionsOf type: some TypeSyntaxProtocol,
conformingTo protocols: [TypeSyntax],
in context: some MacroExpansionContext
) throws -> [ExtensionDeclSyntax] {
let typeName = declaration.declGroupName
return protocols.map {
("""
extension \(typeName): \($0) {
struct _Extension_\($0): \($0) {}
}
""" as DeclSyntax)
.cast(ExtensionDeclSyntax.self)
}
}
}

extension DeclSyntaxProtocol {
var declName: TokenSyntax {
if let varDecl = self.as(VariableDeclSyntax.self),
let first = varDecl.bindings.first,
let pattern = first.pattern.as(IdentifierPatternSyntax.self) {
return pattern.identifier.trimmed
} else if let funcDecl = self.as(FunctionDeclSyntax.self) {
return funcDecl.name.trimmed
} else if let structDecl = self.as(StructDeclSyntax.self) {
return structDecl.name.trimmed
}
fatalError("Not implemented")
}
}

extension DeclGroupSyntax {
var declGroupName: TokenSyntax {
if let structDecl = self.as(StructDeclSyntax.self) {
return structDecl.name.trimmed
}
fatalError("Not implemented")
}
}
41 changes: 41 additions & 0 deletions test/Reflection/preserve_conformance_metadata_attr_macros.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// REQUIRES: objc_interop
// RUN: %empty-directory(%t)
// RUN: %empty-directory(%t/includes)

// Build support Protocols module
// RUN: %target-build-swift %S/Inputs/PreservedConformanceProtocols.swift -parse-as-library -emit-module -emit-library -module-name PreservedConformanceProtocols -o %t/includes/PreservedConformanceProtocols.o

// Build the macro library
// RUN: %host-build-swift -swift-version 5 -emit-library -o %t/%target-library-name(MacroDefinition) -module-name=MacroDefinition %S/Inputs/Macros.swift -g -no-toolchain-stdlib-rpath

// Build the test into a binary
// RUN: %target-build-swift %s -parse-as-library -emit-module -emit-library -module-name PreservedConformances -O -whole-module-optimization -I %t/includes -o %t/PreservedConformances -Xlinker %t/includes/PreservedConformanceProtocols.o -load-plugin-library %t/%target-library-name(MacroDefinition)

// RUN: %target-swift-reflection-dump %t/PreservedConformances | %FileCheck %s

import PreservedConformanceProtocols

@freestanding(declaration, names: named(MacroAddedStruct))
macro AddMacroAddedStruct() = #externalMacro(module: "MacroDefinition", type: "AddStructDeclMacro")

@attached(peer, names: prefixed(_Peer_))
macro AddPeerStruct() = #externalMacro(module: "MacroDefinition", type: "AddPeerStructMacro")

@attached(extension, conformances: TestEntity, names: prefixed(_extension_), named(_Extension_TestEntity))
macro AddExtension() = #externalMacro(module: "MacroDefinition", type: "AddExtensionMacro")

#AddMacroAddedStruct

struct internalTestEntity : TestEntity {}
public struct publicTestEntity : TestEntity {}
@AddPeerStruct
struct internalMacroAidedEntityHelper {}
@AddExtension
struct internalMacroExtensionAidedEntityHelper {}
// CHECK: CONFORMANCES:
// CHECK: =============
// CHECK-DAG: 21PreservedConformances16publicTestEntityV (PreservedConformances.publicTestEntity) : PreservedConformanceProtocols.TestEntity
// CHECK-DAG: 21PreservedConformances18internalTestEntityV (PreservedConformances.internalTestEntity) : PreservedConformanceProtocols.TestEntity
// CHECK-DAG: 21PreservedConformances16MacroAddedStructV (PreservedConformances.MacroAddedStruct) : PreservedConformanceProtocols.TestEntity
// CHECK-DAG: 21PreservedConformances36_Peer_internalMacroAidedEntityHelperV (PreservedConformances._Peer_internalMacroAidedEntityHelper) : PreservedConformanceProtocols.TestEntity
// CHECK-DAG: 21PreservedConformances39internalMacroExtensionAidedEntityHelperV (PreservedConformances.internalMacroExtensionAidedEntityHelper) : PreservedConformanceProtocols.TestEntity