mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[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
This commit is contained in:
@@ -984,12 +984,13 @@ void writeProperties(llvm::json::OStream &JSON,
|
||||
void writeConformances(llvm::json::OStream &JSON,
|
||||
const NominalTypeDecl &NomTypeDecl) {
|
||||
JSON.attributeArray("conformances", [&] {
|
||||
for (auto *Protocol : NomTypeDecl.getAllProtocols()) {
|
||||
for (auto *Conformance : NomTypeDecl.getAllConformances()) {
|
||||
auto Proto = Conformance->getProtocol();
|
||||
// FIXME(noncopyable_generics): Should these be included?
|
||||
if (Protocol->getInvertibleProtocolKind())
|
||||
if (Proto->getInvertibleProtocolKind())
|
||||
continue;
|
||||
|
||||
JSON.value(toFullyQualifiedProtocolNameString(*Protocol));
|
||||
JSON.value(toFullyQualifiedProtocolNameString(*Proto));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
28
test/ConstExtraction/ExtractMacroExpandedConformances.swift
Normal file
28
test/ConstExtraction/ExtractMacroExpandedConformances.swift
Normal file
@@ -0,0 +1,28 @@
|
||||
// REQUIRES: swift_swift_parser
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: echo "[MyProto]" > %t/protocols.json
|
||||
|
||||
// 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
|
||||
|
||||
// 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)
|
||||
// RUN: cat %t/ExtractFromMacroExpansion.swiftconstvalues 2>&1 | %FileCheck %s
|
||||
|
||||
protocol MyProto { }
|
||||
protocol MyExtraProto { }
|
||||
|
||||
@attached(extension, conformances: MyProto, MyExtraProto)
|
||||
macro specificExtensionMacro() = #externalMacro(module: "MacroDefinition", type: "AddSpecificExtensionMacro")
|
||||
|
||||
@specificExtensionMacro
|
||||
struct MyStruct {
|
||||
struct Inner { }
|
||||
}
|
||||
|
||||
// CHECK: "typeName": "ExtractMacroExpandedConformances.MyStruct",
|
||||
// CHECK: "mangledTypeName": "32ExtractMacroExpandedConformances8MyStructV",
|
||||
// CHECK: "kind": "struct",
|
||||
// CHECK: "conformances": [
|
||||
// CHECK-DAG: "Swift.Sendable",
|
||||
// CHECK-DAG: "Swift.BitwiseCopyable",
|
||||
// CHECK-DAG: "ExtractMacroExpandedConformances.MyProto"
|
||||
// CHECK-NOT: "ExtractMacroExpandedConformances.MyExtraProto"
|
||||
@@ -61,6 +61,23 @@ public struct AddExtensionMacro: ExtensionMacro {
|
||||
}
|
||||
}
|
||||
|
||||
public struct AddSpecificExtensionMacro: 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] {
|
||||
var extensions = [ExtensionDeclSyntax]()
|
||||
let protocolNames = Set(protocols.compactMap { $0.as(IdentifierTypeSyntax.self)?.name.text })
|
||||
if protocolNames.contains("MyProto") {
|
||||
extensions.append(try ExtensionDeclSyntax("extension \(type.trimmed): MyProto") { })
|
||||
}
|
||||
return extensions
|
||||
}
|
||||
}
|
||||
|
||||
public struct AddPeerVarMacro: PeerMacro {
|
||||
public static func expansion(
|
||||
of node: AttributeSyntax,
|
||||
|
||||
Reference in New Issue
Block a user