Skip to content

Commit f5f0c00

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 fbe7d89 commit f5f0c00

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
@@ -984,12 +984,13 @@ void writeProperties(llvm::json::OStream &JSON,
984984
void writeConformances(llvm::json::OStream &JSON,
985985
const NominalTypeDecl &NomTypeDecl) {
986986
JSON.attributeArray("conformances", [&] {
987-
for (auto *Protocol : NomTypeDecl.getAllProtocols()) {
987+
for (auto *Conformance : NomTypeDecl.getAllConformances()) {
988+
auto Proto = Conformance->getProtocol();
988989
// FIXME(noncopyable_generics): Should these be included?
989-
if (Protocol->getInvertibleProtocolKind())
990+
if (Proto->getInvertibleProtocolKind())
990991
continue;
991992

992-
JSON.value(toFullyQualifiedProtocolNameString(*Protocol));
993+
JSON.value(toFullyQualifiedProtocolNameString(*Proto));
993994
}
994995
});
995996
}
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)