Skip to content

Commit 14147bf

Browse files
authored
Merge pull request #80428 from tshortli/custom-availability-domain-scopes
AST: Build availability scopes for custom domain conditionals
2 parents 18bffd4 + 303f7d8 commit 14147bf

16 files changed

+715
-235
lines changed

include/swift/AST/AvailabilityContext.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,9 @@ class AvailabilityContext {
9999
void constrainWithContext(const AvailabilityContext &other,
100100
const ASTContext &ctx);
101101

102-
/// Constrain the platform availability range with `platformRange`.
102+
/// Constrain the platform version range with `range`.
103103
// FIXME: [availability] Remove; superseded by constrainWithAvailableRange().
104-
void constrainWithPlatformRange(const AvailabilityRange &platformRange,
104+
void constrainWithPlatformRange(const AvailabilityRange &range,
105105
const ASTContext &ctx);
106106

107107
/// Constrain the available range for `domain` by `range`.

include/swift/AST/AvailabilityDomain.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,10 @@ class AvailabilityDomain final {
217217
/// compilation context.
218218
bool isActive(const ASTContext &ctx) const;
219219

220+
/// Returns true if this domain is a platform domain and is considered active
221+
/// in the current compilation context.
222+
bool isActivePlatform(const ASTContext &ctx) const;
223+
220224
/// Returns the domain's minimum available range for type checking. For
221225
/// example, for the domain of the platform that compilation is targeting,
222226
/// this version is specified with the `-target` option. For the Swift

include/swift/AST/Stmt.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -482,15 +482,15 @@ class alignas(8) PoundAvailableInfo final :
482482

483483
/// The version range when this query will return true. This value is
484484
/// filled in by Sema.
485-
VersionRange AvailableRange;
485+
std::optional<VersionRange> AvailableRange;
486486

487487
/// For zippered builds, this is the version range for the target variant
488488
/// that must hold for the query to return true. For example, when
489489
/// compiling with target x86_64-macosx10.15 and target-variant
490490
/// x86_64-ios13.0 a query of #available(macOS 10.22, iOS 20.0, *) will
491491
/// have a variant range of [20.0, +inf).
492492
/// This is filled in by Sema.
493-
VersionRange VariantAvailableRange;
493+
std::optional<VersionRange> VariantAvailableRange;
494494

495495
struct {
496496
unsigned isInvalid : 1;
@@ -538,11 +538,13 @@ class alignas(8) PoundAvailableInfo final :
538538
SourceLoc getLoc() const { return PoundLoc; }
539539
SourceRange getSourceRange() const { return SourceRange(getStartLoc(),
540540
getEndLoc()); }
541-
542-
const VersionRange &getAvailableRange() const { return AvailableRange; }
541+
542+
std::optional<VersionRange> getAvailableRange() const {
543+
return AvailableRange;
544+
}
543545
void setAvailableRange(const VersionRange &Range) { AvailableRange = Range; }
544546

545-
const VersionRange &getVariantAvailableRange() const {
547+
std::optional<VersionRange> getVariantAvailableRange() const {
546548
return VariantAvailableRange;
547549
}
548550
void setVariantAvailableRange(const VersionRange &Range) {

lib/AST/AvailabilityContext.cpp

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ AvailabilityContext::getAvailabilityRange(AvailabilityDomain domain,
223223
const ASTContext &ctx) const {
224224
DEBUG_ASSERT(domain.supportsContextRefinement());
225225

226-
if (domain.isActive(ctx) && domain.isPlatform())
226+
if (domain.isActivePlatform(ctx))
227227
return storage->platformRange;
228228

229229
for (auto domainInfo : storage->getDomainInfos()) {
@@ -287,8 +287,9 @@ void AvailabilityContext::constrainWithPlatformRange(
287287
void AvailabilityContext::constrainWithAvailabilityRange(
288288
const AvailabilityRange &range, AvailabilityDomain domain,
289289
const ASTContext &ctx) {
290+
DEBUG_ASSERT(domain.supportsContextRefinement());
290291

291-
if (domain.isActive(ctx) && domain.isPlatform()) {
292+
if (domain.isActivePlatform(ctx)) {
292293
constrainWithPlatformRange(range, ctx);
293294
return;
294295
}
@@ -344,7 +345,7 @@ void AvailabilityContext::constrainWithDeclAndPlatformRange(
344345
break;
345346
case AvailabilityConstraint::Reason::PotentiallyUnavailable:
346347
if (auto introducedRange = attr.getIntroducedRange(ctx)) {
347-
if (domain.isActive(ctx) && domain.isPlatform()) {
348+
if (domain.isActivePlatform(ctx)) {
348349
isConstrained |= constrainRange(platformRange, *introducedRange);
349350
} else {
350351
declDomainInfos.push_back({domain, *introducedRange});
@@ -403,12 +404,35 @@ void AvailabilityContext::print(llvm::raw_ostream &os) const {
403404
os << "version=" << stringForAvailability(getPlatformRange());
404405

405406
auto domainInfos = storage->getDomainInfos();
406-
if (domainInfos.size() > 0) {
407-
os << " unavailable=";
408-
llvm::interleave(
409-
domainInfos, os,
410-
[&](const DomainInfo &domainInfo) { domainInfo.getDomain().print(os); },
411-
",");
407+
if (!domainInfos.empty()) {
408+
auto availableInfos = llvm::make_filter_range(
409+
domainInfos, [](auto info) { return !info.isUnavailable(); });
410+
411+
if (!availableInfos.empty()) {
412+
os << " available=";
413+
llvm::interleave(
414+
availableInfos, os,
415+
[&](const DomainInfo &domainInfo) {
416+
domainInfo.getDomain().print(os);
417+
if (domainInfo.getDomain().isVersioned() &&
418+
domainInfo.getRange().hasMinimumVersion())
419+
os << ">=" << domainInfo.getRange().getAsString();
420+
},
421+
",");
422+
}
423+
424+
auto unavailableInfos = llvm::make_filter_range(
425+
domainInfos, [](auto info) { return info.isUnavailable(); });
426+
427+
if (!unavailableInfos.empty()) {
428+
os << " unavailable=";
429+
llvm::interleave(
430+
unavailableInfos, os,
431+
[&](const DomainInfo &domainInfo) {
432+
domainInfo.getDomain().print(os);
433+
},
434+
",");
435+
}
412436
}
413437

414438
if (isDeprecated())

lib/AST/AvailabilityDomain.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,13 @@ bool AvailabilityDomain::isActive(const ASTContext &ctx) const {
100100
}
101101
}
102102

103+
bool AvailabilityDomain::isActivePlatform(const ASTContext &ctx) const {
104+
if (!isPlatform())
105+
return false;
106+
107+
return isActive(ctx);
108+
}
109+
103110
static std::optional<llvm::VersionTuple>
104111
getDeploymentVersion(const AvailabilityDomain &domain, const ASTContext &ctx) {
105112
switch (domain.getKind()) {

0 commit comments

Comments
 (0)