Sema: Generalize more-available-than-enclosing-decl diagnostics.

NFC.
This commit is contained in:
Allan Shortlidge
2025-07-17 21:24:14 -07:00
parent 034c62cf01
commit 5601e66a69
2 changed files with 29 additions and 12 deletions

View File

@@ -2200,13 +2200,19 @@ static Decl *getEnclosingDeclForDecl(Decl *D) {
}
static std::optional<std::pair<SemanticAvailableAttr, const Decl *>>
getSemanticAvailableRangeDeclAndAttr(const Decl *decl) {
if (auto attr = decl->getAvailableAttrForPlatformIntroduction(
/*checkExtension=*/false))
return std::make_pair(*attr, decl);
getSemanticAvailableRangeDeclAndAttr(const Decl *decl,
AvailabilityDomain domain) {
auto &ctx = decl->getASTContext();
AvailabilityConstraintFlags flags =
AvailabilityConstraintFlag::SkipEnclosingExtension;
if (auto constraint = swift::getAvailabilityConstraintForDeclInDomain(
decl, AvailabilityContext::forAlwaysAvailable(ctx), domain, flags)) {
if (constraint->isPotentiallyAvailable())
return std::make_pair(constraint->getAttr(), decl);
}
if (auto *parent = decl->parentDeclForAvailability())
return getSemanticAvailableRangeDeclAndAttr(parent);
return getSemanticAvailableRangeDeclAndAttr(parent, domain);
return std::nullopt;
}
@@ -2300,7 +2306,7 @@ void AttributeChecker::visitAvailableAttr(AvailableAttr *parsedAttr) {
if (auto *parent = getEnclosingDeclForDecl(D)) {
if (auto enclosingAvailable =
getSemanticAvailableRangeDeclAndAttr(parent)) {
getSemanticAvailableRangeDeclAndAttr(parent, attr->getDomain())) {
SemanticAvailableAttr enclosingAttr = enclosingAvailable->first;
const Decl *enclosingDecl = enclosingAvailable->second;
enclosingIntroducedRange = enclosingAttr.getIntroducedRange(Ctx);
@@ -5245,8 +5251,8 @@ void AttributeChecker::checkBackDeployedAttrs(
// If it's not, the attribute doesn't make sense since the back deployment
// fallback could never be executed at runtime.
if (auto availableRangeAttrPair =
getSemanticAvailableRangeDeclAndAttr(VD)) {
auto beforeDomain = Attr->getAvailabilityDomain();
getSemanticAvailableRangeDeclAndAttr(VD, Domain)) {
auto beforeDomain = Domain;
auto beforeVersion = Attr->getVersion();
auto availableAttr = availableRangeAttrPair.value().first;
auto introVersion = availableAttr.getIntroduced().value();

View File

@@ -231,18 +231,29 @@ func testFixIts() {
// expected-note@-1 {{add 'if #available' version check}}{{3-29=if #available(EnabledDomain) {\n availableInEnabledDomain()\n \} else {\n // Fallback\n \}}}
}
struct Container { }
@available(EnabledDomain)
extension Container {
@available(EnabledDomain)
func redundantlyAvailableInEnabledDomain() { }
@available(EnabledDomain, unavailable)
func unavailableInEnabledDomain() { }
}
protocol P { }
@available(EnabledDomain)
struct AvailableInEnabledDomain: P { }
struct AvailableConformsToP: P { }
@available(EnabledDomain, unavailable)
struct UnavailableInEnabledDomain: P { }
struct UnavailableConformsToP: P { }
func testOpaqueReturnType() -> some P {
if #available(EnabledDomain) { // expected-error {{opaque return type cannot depend on EnabledDomain availability}}
return AvailableInEnabledDomain()
return AvailableConformsToP()
} else {
return UnavailableInEnabledDomain()
return UnavailableConformsToP()
}
}