Skip to content

Commit a4da07e

Browse files
authored
Merge pull request #84070 from tshortli/universally-unavailable-at-runtime
AST: Fix runtime unavailability for universally unavailable decls
2 parents 7fb532e + e390cce commit a4da07e

File tree

6 files changed

+83
-35
lines changed

6 files changed

+83
-35
lines changed

include/swift/AST/AvailabilityConstraint.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,14 @@ std::optional<AvailabilityConstraint> getAvailabilityConstraintForDeclInDomain(
240240
const Decl *decl, const AvailabilityContext &context,
241241
AvailabilityDomain domain,
242242
AvailabilityConstraintFlags flags = std::nullopt);
243+
244+
/// Computes the set of constraints that indicate whether a decl is "runtime
245+
/// unavailable" (can never be reached at runtime) and adds the domain for each
246+
/// of those constraints to the \p domains vector.
247+
void getRuntimeUnavailableDomains(
248+
const DeclAvailabilityConstraints &constraints,
249+
llvm::SmallVectorImpl<AvailabilityDomain> &domains, const ASTContext &ctx);
250+
243251
} // end namespace swift
244252

245253
namespace llvm {

lib/AST/Availability.cpp

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -574,27 +574,6 @@ getRootTargetDomains(const ASTContext &ctx) {
574574
return domains;
575575
}
576576

577-
static bool constraintIndicatesRuntimeUnavailability(
578-
const AvailabilityConstraint &constraint, const ASTContext &ctx) {
579-
std::optional<CustomAvailabilityDomain::Kind> customDomainKind;
580-
if (auto customDomain = constraint.getDomain().getCustomDomain())
581-
customDomainKind = customDomain->getKind();
582-
583-
switch (constraint.getReason()) {
584-
case AvailabilityConstraint::Reason::UnavailableUnconditionally:
585-
if (customDomainKind)
586-
return customDomainKind == CustomAvailabilityDomain::Kind::Enabled;
587-
return true;
588-
case AvailabilityConstraint::Reason::UnavailableObsolete:
589-
case AvailabilityConstraint::Reason::UnavailableUnintroduced:
590-
return false;
591-
case AvailabilityConstraint::Reason::Unintroduced:
592-
if (customDomainKind)
593-
return customDomainKind == CustomAvailabilityDomain::Kind::Disabled;
594-
return false;
595-
}
596-
}
597-
598577
/// Returns true if a decl that is unavailable in the given domain must still be
599578
/// emitted to preserve load time ABI compatibility.
600579
static bool
@@ -633,10 +612,7 @@ computeDeclRuntimeAvailability(const Decl *decl) {
633612

634613
// First, collect the unavailable domains from the constraints.
635614
llvm::SmallVector<AvailabilityDomain, 8> unavailableDomains;
636-
for (auto constraint : constraints) {
637-
if (constraintIndicatesRuntimeUnavailability(constraint, ctx))
638-
unavailableDomains.push_back(constraint.getDomain());
639-
}
615+
getRuntimeUnavailableDomains(constraints, unavailableDomains, ctx);
640616

641617
// Check whether there are any available attributes that would make the
642618
// decl available in descendants of the unavailable domains.
@@ -647,6 +623,10 @@ computeDeclRuntimeAvailability(const Decl *decl) {
647623
continue;
648624

649625
llvm::erase_if(unavailableDomains, [domain](auto unavailableDomain) {
626+
// Unavailability in '*' cannot be superseded by an @available attribute
627+
// for a more specific availability domain.
628+
if (unavailableDomain.isUniversal())
629+
return false;
650630
return unavailableDomain.contains(domain);
651631
});
652632
}

lib/AST/AvailabilityConstraint.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,3 +322,33 @@ swift::getAvailabilityConstraintForDeclInDomain(
322322

323323
return std::nullopt;
324324
}
325+
326+
static bool constraintIndicatesRuntimeUnavailability(
327+
const AvailabilityConstraint &constraint, const ASTContext &ctx) {
328+
std::optional<CustomAvailabilityDomain::Kind> customDomainKind;
329+
if (auto customDomain = constraint.getDomain().getCustomDomain())
330+
customDomainKind = customDomain->getKind();
331+
332+
switch (constraint.getReason()) {
333+
case AvailabilityConstraint::Reason::UnavailableUnconditionally:
334+
if (customDomainKind)
335+
return customDomainKind == CustomAvailabilityDomain::Kind::Enabled;
336+
return true;
337+
case AvailabilityConstraint::Reason::UnavailableObsolete:
338+
case AvailabilityConstraint::Reason::UnavailableUnintroduced:
339+
return false;
340+
case AvailabilityConstraint::Reason::Unintroduced:
341+
if (customDomainKind)
342+
return customDomainKind == CustomAvailabilityDomain::Kind::Disabled;
343+
return false;
344+
}
345+
}
346+
347+
void swift::getRuntimeUnavailableDomains(
348+
const DeclAvailabilityConstraints &constraints,
349+
llvm::SmallVectorImpl<AvailabilityDomain> &domains, const ASTContext &ctx) {
350+
for (auto constraint : constraints) {
351+
if (constraintIndicatesRuntimeUnavailability(constraint, ctx))
352+
domains.push_back(constraint.getDomain());
353+
}
354+
}

test/SILGen/unavailable_decl_custom_domain.swift

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,15 @@
33
// RUN: -define-enabled-availability-domain EnabledDomain \
44
// RUN: -define-disabled-availability-domain DisabledDomain \
55
// RUN: -define-dynamic-availability-domain DynamicDomain \
6-
// RUN: | %FileCheck %s
7-
8-
// RUN: %target-swift-emit-silgen -module-name Test %s -verify \
9-
// RUN: -enable-experimental-feature CustomAvailability \
10-
// RUN: -define-enabled-availability-domain EnabledDomain \
11-
// RUN: -define-disabled-availability-domain DisabledDomain \
12-
// RUN: -define-dynamic-availability-domain DynamicDomain \
13-
// RUN: -unavailable-decl-optimization=stub \
14-
// RUN: | %FileCheck %s
6+
// RUN: | %FileCheck %s --check-prefixes=CHECK,CHECK-NOOPT
157

168
// RUN: %target-swift-emit-silgen -module-name Test %s -verify \
179
// RUN: -enable-experimental-feature CustomAvailability \
1810
// RUN: -define-enabled-availability-domain EnabledDomain \
1911
// RUN: -define-disabled-availability-domain DisabledDomain \
2012
// RUN: -define-dynamic-availability-domain DynamicDomain \
2113
// RUN: -unavailable-decl-optimization=complete \
22-
// RUN: | %FileCheck %s
14+
// RUN: | %FileCheck %s --check-prefixes=CHECK,CHECK-OPT
2315

2416
// REQUIRES: swift_feature_CustomAvailability
2517

@@ -84,3 +76,25 @@ public func availableInEnabledAndDisabledDomain() { }
8476
@available(DisabledDomain)
8577
@available(EnabledDomain)
8678
public func availableInDisabledAndEnabledDomain() { }
79+
80+
// CHECK-NOOPT: s4Test49availableInEnabledDomainAndUnavailableUniversallyyyF
81+
// CHECK-OPT-NOT: s4Test49availableInEnabledDomainAndUnavailableUniversallyyyF
82+
@available(*, unavailable)
83+
@available(EnabledDomain)
84+
public func availableInEnabledDomainAndUnavailableUniversally() { }
85+
86+
// CHECK-NOT: s4Test40unavailableInEnabledDomainAndUniversallyyyF
87+
@available(*, unavailable)
88+
@available(EnabledDomain, unavailable)
89+
public func unavailableInEnabledDomainAndUniversally() { }
90+
91+
// CHECK-NOT: s4Test50availableInDisabledDomainAndUnavailableUniversallyyyF
92+
@available(*, unavailable)
93+
@available(DisabledDomain)
94+
public func availableInDisabledDomainAndUnavailableUniversally() { }
95+
96+
// CHECK-NOOPT: s4Test41unavailableInDisabledDomainAndUniversallyyyF
97+
// CHECK-OPT-NOT: s4Test41unavailableInDisabledDomainAndUniversallyyyF
98+
@available(*, unavailable)
99+
@available(DisabledDomain, unavailable)
100+
public func unavailableInDisabledDomainAndUniversally() { }

test/SILGen/unavailable_decl_optimization_stub.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@ public func unavailableFunc() -> S {
1212
return S()
1313
}
1414

15+
// CHECK-LABEL: sil{{.*}}@$s4Test33unavailableFuncIntroducedInSwift5yyF
16+
// CHECK: [[FNREF:%.*]] = function_ref @$[[DIAGNOSEFN:(ss31_diagnoseUnavailableCodeReacheds5NeverOyF|ss31_diagnoseUnavailableCodeReacheds5NeverOyFTwb)]] : $@convention(thin) () -> Never
17+
// CHECK-NEXT: [[APPLY:%.*]] = apply [[FNREF]]()
18+
// CHECK: } // end sil function '$s4Test33unavailableFuncIntroducedInSwift5yyF'
19+
@available(*, unavailable)
20+
@available(swift 5)
21+
public func unavailableFuncIntroducedInSwift5() { }
22+
1523
// CHECK-LABEL: sil{{.*}}@$s4Test025unavailableFuncWithNestedC0yyF
1624
// CHECK: [[FNREF:%.*]] = function_ref @$[[DIAGNOSEFN:(ss31_diagnoseUnavailableCodeReacheds5NeverOyF|ss31_diagnoseUnavailableCodeReacheds5NeverOyFTwb)]] : $@convention(thin) () -> Never
1725
// CHECK-NEXT: [[APPLY:%.*]] = apply [[FNREF]]()

test/SILGen/unavailable_decl_optimization_stub_macos.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@ public func unavailableFunc() {}
2424
@available(macOS, unavailable)
2525
public func unavailableOnMacOSFunc() {}
2626

27+
// CHECK-LABEL: sil{{.*}}@$s4Test36unavailableFuncWithMacOSIntroductionyyF
28+
// CHECK: [[FNREF:%.*]] = function_ref @$ss31_diagnoseUnavailableCodeReacheds5NeverOyFTwb : $@convention(thin) () -> Never
29+
// CHECK-NEXT: [[APPLY:%.*]] = apply [[FNREF]]()
30+
// CHECK: } // end sil function '$s4Test36unavailableFuncWithMacOSIntroductionyyF'
31+
@available(*, unavailable)
32+
@available(macOS 12.0, *)
33+
public func unavailableFuncWithMacOSIntroduction() {}
34+
2735
// CHECK-LABEL: sil{{.*}}@$s4Test31unavailableOnMacOSExtensionFuncyyF
2836
// CHECK-NOT: _diagnoseUnavailableCodeReached
2937
// CHECK: } // end sil function '$s4Test31unavailableOnMacOSExtensionFuncyyF'

0 commit comments

Comments
 (0)