ModuleInterface: Fix availability attributes on synthesized conformances.

Adjust the algorithm that collects the availability attributes for synthesized
conformances to ensure it skips attributes from parent declarations that are
superceded by attributes in nested declarations, even when the domains of those
attributes do not match exactly.
This commit is contained in:
Allan Shortlidge
2026-03-03 17:14:43 -08:00
parent bdc4f45eea
commit 457debcf4d
2 changed files with 78 additions and 6 deletions
+15 -6
View File
@@ -452,18 +452,27 @@ class InheritedProtocolCollector {
return cache.value();
cache.emplace();
// Start with the decl itself and add its @available attributes to the list.
// Then do the same for each parent declaration, but skip adding new
// availability attributes if they would be superceded by an attribute on a
// nested declaration since those take precedence.
// FIXME: This is just approximating the effects of nested availability
// attributes for the same platform; formally they'd need to be merged.
llvm::SmallVector<SemanticAvailableAttr, 8> pendingAttrs;
while (D) {
for (auto nextAttr : D->getSemanticAvailableAttrs()) {
// FIXME: This is just approximating the effects of nested availability
// attributes for the same platform; formally they'd need to be merged.
bool alreadyHasMoreSpecificAttrForThisPlatform = llvm::any_of(
bool hasMoreSpecificAttribute = llvm::any_of(
*cache, [nextAttr](SemanticAvailableAttr existingAttr) {
return existingAttr.getDomain() == nextAttr.getDomain();
return existingAttr.getDomain().contains(nextAttr.getDomain());
});
if (alreadyHasMoreSpecificAttrForThisPlatform)
if (hasMoreSpecificAttribute)
continue;
cache->push_back(nextAttr);
pendingAttrs.push_back(nextAttr);
}
cache->append(pendingAttrs);
pendingAttrs.clear();
D = D->getDeclContext()->getAsDecl();
}