From df11fdec6b344cda5ec48eb734892e39871aad13 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Thu, 10 Aug 2023 18:19:33 -0700 Subject: [PATCH] [Macros] Always consider pre-macro-expansion conformances as subsumed by other conformance entry kinds, before considering availability. (cherry picked from commit 309e3403f6a343ea026079d9f7b6cfe507b91c2d) --- lib/AST/ConformanceLookupTable.cpp | 28 +++++++++---------- .../Inputs/syntax_macro_definitions.swift | 20 +++++++++++++ test/Macros/macro_expand_extensions.swift | 9 ++++++ 3 files changed, 43 insertions(+), 14 deletions(-) diff --git a/lib/AST/ConformanceLookupTable.cpp b/lib/AST/ConformanceLookupTable.cpp index 81b0d4e3849cb..f513af269208b 100644 --- a/lib/AST/ConformanceLookupTable.cpp +++ b/lib/AST/ConformanceLookupTable.cpp @@ -565,20 +565,6 @@ ConformanceLookupTable::Ordering ConformanceLookupTable::compareConformances( ConformanceEntry *lhs, ConformanceEntry *rhs, bool &diagnoseSuperseded) { - // If only one of the conformances is unconditionally available on the - // current deployment target, pick that one. - // - // FIXME: Conformance lookup should really depend on source location for - // this to be 100% correct. - // FIXME: When a class and an extension with the same availability declare the - // same conformance, this silently takes the class and drops the extension. - if (lhs->getDeclContext()->isAlwaysAvailableConformanceContext() != - rhs->getDeclContext()->isAlwaysAvailableConformanceContext()) { - return (lhs->getDeclContext()->isAlwaysAvailableConformanceContext() - ? Ordering::Before - : Ordering::After); - } - ConformanceEntryKind lhsKind = lhs->getRankingKind(); ConformanceEntryKind rhsKind = rhs->getRankingKind(); @@ -596,6 +582,20 @@ ConformanceLookupTable::Ordering ConformanceLookupTable::compareConformances( } } + // If only one of the conformances is unconditionally available on the + // current deployment target, pick that one. + // + // FIXME: Conformance lookup should really depend on source location for + // this to be 100% correct. + // FIXME: When a class and an extension with the same availability declare the + // same conformance, this silently takes the class and drops the extension. + if (lhs->getDeclContext()->isAlwaysAvailableConformanceContext() != + rhs->getDeclContext()->isAlwaysAvailableConformanceContext()) { + return (lhs->getDeclContext()->isAlwaysAvailableConformanceContext() + ? Ordering::Before + : Ordering::After); + } + // If one entry is fixed and the other is not, we have our answer. if (lhs->isFixed() != rhs->isFixed()) { auto isReplaceableOrMarker = [](ConformanceEntry *entry) -> bool { diff --git a/test/Macros/Inputs/syntax_macro_definitions.swift b/test/Macros/Inputs/syntax_macro_definitions.swift index 4d75327807139..375f8db68986b 100644 --- a/test/Macros/Inputs/syntax_macro_definitions.swift +++ b/test/Macros/Inputs/syntax_macro_definitions.swift @@ -1461,6 +1461,26 @@ public struct AlwaysAddConformance: ExtensionMacro { } } +public struct ConditionallyAvailableConformance: ExtensionMacro { + public static func expansion( + of node: AttributeSyntax, + attachedTo decl: some DeclGroupSyntax, + providingExtensionsOf type: some TypeSyntaxProtocol, + conformingTo protocols: [TypeSyntax], + in context: some MacroExpansionContext + ) throws -> [ExtensionDeclSyntax] { + let decl: DeclSyntax = + """ + @available(macOS 99, *) + extension \(raw: type.trimmedDescription): Equatable {} + """ + + return [ + decl.cast(ExtensionDeclSyntax.self) + ] + } +} + public struct AlwaysAddCodable: ExtensionMacro { public static func expansion( of node: AttributeSyntax, diff --git a/test/Macros/macro_expand_extensions.swift b/test/Macros/macro_expand_extensions.swift index 337f723d4b672..e4f2d4430bed2 100644 --- a/test/Macros/macro_expand_extensions.swift +++ b/test/Macros/macro_expand_extensions.swift @@ -156,3 +156,12 @@ struct TestUndocumentedEncodable {} // CHECK-DIAGS: error: conformance to 'Codable' (aka 'Decodable & Encodable') is not covered by macro 'UndocumentedEncodable' #endif + +@attached(extension, conformances: Equatable) +macro AvailableEquatable() = #externalMacro(module: "MacroDefinition", type: "ConditionallyAvailableConformance") + +@available(macOS 99, *) +@AvailableEquatable +struct TestAvailability { + static let x : any Equatable.Type = TestAvailability.self +}