Skip to content

Commit 309e340

Browse files
committed
[Macros] Always consider pre-macro-expansion conformances as subsumed by
other conformance entry kinds, before considering availability.
1 parent 6261ee2 commit 309e340

File tree

3 files changed

+43
-14
lines changed

3 files changed

+43
-14
lines changed

lib/AST/ConformanceLookupTable.cpp

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -565,20 +565,6 @@ ConformanceLookupTable::Ordering ConformanceLookupTable::compareConformances(
565565
ConformanceEntry *lhs,
566566
ConformanceEntry *rhs,
567567
bool &diagnoseSuperseded) {
568-
// If only one of the conformances is unconditionally available on the
569-
// current deployment target, pick that one.
570-
//
571-
// FIXME: Conformance lookup should really depend on source location for
572-
// this to be 100% correct.
573-
// FIXME: When a class and an extension with the same availability declare the
574-
// same conformance, this silently takes the class and drops the extension.
575-
if (lhs->getDeclContext()->isAlwaysAvailableConformanceContext() !=
576-
rhs->getDeclContext()->isAlwaysAvailableConformanceContext()) {
577-
return (lhs->getDeclContext()->isAlwaysAvailableConformanceContext()
578-
? Ordering::Before
579-
: Ordering::After);
580-
}
581-
582568
ConformanceEntryKind lhsKind = lhs->getRankingKind();
583569
ConformanceEntryKind rhsKind = rhs->getRankingKind();
584570

@@ -596,6 +582,20 @@ ConformanceLookupTable::Ordering ConformanceLookupTable::compareConformances(
596582
}
597583
}
598584

585+
// If only one of the conformances is unconditionally available on the
586+
// current deployment target, pick that one.
587+
//
588+
// FIXME: Conformance lookup should really depend on source location for
589+
// this to be 100% correct.
590+
// FIXME: When a class and an extension with the same availability declare the
591+
// same conformance, this silently takes the class and drops the extension.
592+
if (lhs->getDeclContext()->isAlwaysAvailableConformanceContext() !=
593+
rhs->getDeclContext()->isAlwaysAvailableConformanceContext()) {
594+
return (lhs->getDeclContext()->isAlwaysAvailableConformanceContext()
595+
? Ordering::Before
596+
: Ordering::After);
597+
}
598+
599599
// If one entry is fixed and the other is not, we have our answer.
600600
if (lhs->isFixed() != rhs->isFixed()) {
601601
auto isReplaceableOrMarker = [](ConformanceEntry *entry) -> bool {

test/Macros/Inputs/syntax_macro_definitions.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1423,6 +1423,26 @@ public struct AlwaysAddConformance: ExtensionMacro {
14231423
}
14241424
}
14251425

1426+
public struct ConditionallyAvailableConformance: ExtensionMacro {
1427+
public static func expansion(
1428+
of node: AttributeSyntax,
1429+
attachedTo decl: some DeclGroupSyntax,
1430+
providingExtensionsOf type: some TypeSyntaxProtocol,
1431+
conformingTo protocols: [TypeSyntax],
1432+
in context: some MacroExpansionContext
1433+
) throws -> [ExtensionDeclSyntax] {
1434+
let decl: DeclSyntax =
1435+
"""
1436+
@available(macOS 99, *)
1437+
extension \(raw: type.trimmedDescription): Equatable {}
1438+
"""
1439+
1440+
return [
1441+
decl.cast(ExtensionDeclSyntax.self)
1442+
]
1443+
}
1444+
}
1445+
14261446
public struct AlwaysAddCodable: ExtensionMacro {
14271447
public static func expansion(
14281448
of node: AttributeSyntax,

test/Macros/macro_expand_extensions.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,3 +156,12 @@ struct TestUndocumentedEncodable {}
156156
// CHECK-DIAGS: error: conformance to 'Codable' (aka 'Decodable & Encodable') is not covered by macro 'UndocumentedEncodable'
157157

158158
#endif
159+
160+
@attached(extension, conformances: Equatable)
161+
macro AvailableEquatable() = #externalMacro(module: "MacroDefinition", type: "ConditionallyAvailableConformance")
162+
163+
@available(macOS 99, *)
164+
@AvailableEquatable
165+
struct TestAvailability {
166+
static let x : any Equatable.Type = TestAvailability.self
167+
}

0 commit comments

Comments
 (0)