Skip to content

Commit 250f657

Browse files
committed
[Compile Time Constant Extraction] Query nominal type conformances to get at the protocols, instead of getAllProtocols.
As it stands, for extension macros which add protocol conformances, the list of protocols specified on the macro's 'conformances:' parameter gets added in its entirety to the list of a nominal type's protocols in 'ConformanceLookupTable::addMacroGeneratedProtocols'. Whereas the macro itself, may only add *some* of the specified conformances. This means that `getAllProtocols` may contain a super-set of protocols captured in `getAllConformances`, some of which may not actually be generated by the macro. This change narrowly fixes ConstExtract to query actual generated conformances. Though, potentially we should make 'ConformanceLookupTable::addMacroGeneratedProtocols' behave in a way that reflects the protocols the macro actually adds the conformances to, instead of the ones it may add conformances to. Resolves rdar://130316531
1 parent b4a169e commit 250f657

File tree

3 files changed

+49
-3
lines changed

3 files changed

+49
-3
lines changed

lib/ConstExtract/ConstExtract.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -942,12 +942,13 @@ void writeProperties(llvm::json::OStream &JSON,
942942
void writeConformances(llvm::json::OStream &JSON,
943943
const NominalTypeDecl &NomTypeDecl) {
944944
JSON.attributeArray("conformances", [&] {
945-
for (auto *Protocol : NomTypeDecl.getAllProtocols()) {
945+
for (auto *Conformance : NomTypeDecl.getAllConformances()) {
946+
auto Proto = Conformance->getProtocol();
946947
// FIXME(noncopyable_generics): Should these be included?
947-
if (Protocol->getInvertibleProtocolKind())
948+
if (Proto->getInvertibleProtocolKind())
948949
continue;
949950

950-
JSON.value(toFullyQualifiedProtocolNameString(*Protocol));
951+
JSON.value(toFullyQualifiedProtocolNameString(*Proto));
951952
}
952953
});
953954
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// REQUIRES: swift_swift_parser
2+
// RUN: %empty-directory(%t)
3+
// RUN: echo "[MyProto]" > %t/protocols.json
4+
5+
// 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
6+
7+
// RUN: %target-swift-frontend -typecheck -emit-const-values-path %t/ExtractFromMacroExpansion.swiftconstvalues -const-gather-protocols-file %t/protocols.json -primary-file %s -load-plugin-library %t/%target-library-name(MacroDefinition)
8+
// RUN: cat %t/ExtractFromMacroExpansion.swiftconstvalues 2>&1 | %FileCheck %s
9+
10+
protocol MyProto { }
11+
protocol MyExtraProto { }
12+
13+
@attached(extension, conformances: MyProto, MyExtraProto)
14+
macro specificExtensionMacro() = #externalMacro(module: "MacroDefinition", type: "AddSpecificExtensionMacro")
15+
16+
@specificExtensionMacro
17+
struct MyStruct {
18+
struct Inner { }
19+
}
20+
21+
// CHECK: "typeName": "ExtractMacroExpandedConformances.MyStruct",
22+
// CHECK: "mangledTypeName": "32ExtractMacroExpandedConformances8MyStructV",
23+
// CHECK: "kind": "struct",
24+
// CHECK: "conformances": [
25+
// CHECK-DAG: "Swift.Sendable",
26+
// CHECK-DAG: "Swift.BitwiseCopyable",
27+
// CHECK-DAG: "ExtractMacroExpandedConformances.MyProto"
28+
// CHECK-NOT: "ExtractMacroExpandedConformances.MyExtraProto"

test/ConstExtraction/Inputs/Macros.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,23 @@ public struct AddExtensionMacro: ExtensionMacro {
6161
}
6262
}
6363

64+
public struct AddSpecificExtensionMacro: ExtensionMacro {
65+
public static func expansion(
66+
of node: AttributeSyntax,
67+
attachedTo declaration: some DeclGroupSyntax,
68+
providingExtensionsOf type: some TypeSyntaxProtocol,
69+
conformingTo protocols: [TypeSyntax],
70+
in context: some MacroExpansionContext
71+
) throws -> [ExtensionDeclSyntax] {
72+
var extensions = [ExtensionDeclSyntax]()
73+
let protocolNames = Set(protocols.compactMap { $0.as(IdentifierTypeSyntax.self)?.name.text })
74+
if protocolNames.contains("MyProto") {
75+
extensions.append(try ExtensionDeclSyntax("extension \(type.trimmed): MyProto") { })
76+
}
77+
return extensions
78+
}
79+
}
80+
6481
public struct AddPeerVarMacro: PeerMacro {
6582
public static func expansion(
6683
of node: AttributeSyntax,

0 commit comments

Comments
 (0)