Skip to content

AST: Build availability scopes for custom domain conditionals #80428

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Apr 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions include/swift/AST/AvailabilityContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,9 @@ class AvailabilityContext {
void constrainWithContext(const AvailabilityContext &other,
const ASTContext &ctx);

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

/// Constrain the available range for `domain` by `range`.
Expand Down
4 changes: 4 additions & 0 deletions include/swift/AST/AvailabilityDomain.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,10 @@ class AvailabilityDomain final {
/// compilation context.
bool isActive(const ASTContext &ctx) const;

/// Returns true if this domain is a platform domain and is considered active
/// in the current compilation context.
bool isActivePlatform(const ASTContext &ctx) const;

/// Returns the domain's minimum available range for type checking. For
/// example, for the domain of the platform that compilation is targeting,
/// this version is specified with the `-target` option. For the Swift
Expand Down
12 changes: 7 additions & 5 deletions include/swift/AST/Stmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -482,15 +482,15 @@ class alignas(8) PoundAvailableInfo final :

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

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

struct {
unsigned isInvalid : 1;
Expand Down Expand Up @@ -538,11 +538,13 @@ class alignas(8) PoundAvailableInfo final :
SourceLoc getLoc() const { return PoundLoc; }
SourceRange getSourceRange() const { return SourceRange(getStartLoc(),
getEndLoc()); }

const VersionRange &getAvailableRange() const { return AvailableRange; }

std::optional<VersionRange> getAvailableRange() const {
return AvailableRange;
}
void setAvailableRange(const VersionRange &Range) { AvailableRange = Range; }

const VersionRange &getVariantAvailableRange() const {
std::optional<VersionRange> getVariantAvailableRange() const {
return VariantAvailableRange;
}
void setVariantAvailableRange(const VersionRange &Range) {
Expand Down
42 changes: 33 additions & 9 deletions lib/AST/AvailabilityContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ AvailabilityContext::getAvailabilityRange(AvailabilityDomain domain,
const ASTContext &ctx) const {
DEBUG_ASSERT(domain.supportsContextRefinement());

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

for (auto domainInfo : storage->getDomainInfos()) {
Expand Down Expand Up @@ -287,8 +287,9 @@ void AvailabilityContext::constrainWithPlatformRange(
void AvailabilityContext::constrainWithAvailabilityRange(
const AvailabilityRange &range, AvailabilityDomain domain,
const ASTContext &ctx) {
DEBUG_ASSERT(domain.supportsContextRefinement());

if (domain.isActive(ctx) && domain.isPlatform()) {
if (domain.isActivePlatform(ctx)) {
constrainWithPlatformRange(range, ctx);
return;
}
Expand Down Expand Up @@ -344,7 +345,7 @@ void AvailabilityContext::constrainWithDeclAndPlatformRange(
break;
case AvailabilityConstraint::Reason::PotentiallyUnavailable:
if (auto introducedRange = attr.getIntroducedRange(ctx)) {
if (domain.isActive(ctx) && domain.isPlatform()) {
if (domain.isActivePlatform(ctx)) {
isConstrained |= constrainRange(platformRange, *introducedRange);
} else {
declDomainInfos.push_back({domain, *introducedRange});
Expand Down Expand Up @@ -403,12 +404,35 @@ void AvailabilityContext::print(llvm::raw_ostream &os) const {
os << "version=" << stringForAvailability(getPlatformRange());

auto domainInfos = storage->getDomainInfos();
if (domainInfos.size() > 0) {
os << " unavailable=";
llvm::interleave(
domainInfos, os,
[&](const DomainInfo &domainInfo) { domainInfo.getDomain().print(os); },
",");
if (!domainInfos.empty()) {
auto availableInfos = llvm::make_filter_range(
domainInfos, [](auto info) { return !info.isUnavailable(); });

if (!availableInfos.empty()) {
os << " available=";
llvm::interleave(
availableInfos, os,
[&](const DomainInfo &domainInfo) {
domainInfo.getDomain().print(os);
if (domainInfo.getDomain().isVersioned() &&
domainInfo.getRange().hasMinimumVersion())
os << ">=" << domainInfo.getRange().getAsString();
},
",");
}

auto unavailableInfos = llvm::make_filter_range(
domainInfos, [](auto info) { return info.isUnavailable(); });

if (!unavailableInfos.empty()) {
os << " unavailable=";
llvm::interleave(
unavailableInfos, os,
[&](const DomainInfo &domainInfo) {
domainInfo.getDomain().print(os);
},
",");
}
}

if (isDeprecated())
Expand Down
7 changes: 7 additions & 0 deletions lib/AST/AvailabilityDomain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,13 @@ bool AvailabilityDomain::isActive(const ASTContext &ctx) const {
}
}

bool AvailabilityDomain::isActivePlatform(const ASTContext &ctx) const {
if (!isPlatform())
return false;

return isActive(ctx);
}

static std::optional<llvm::VersionTuple>
getDeploymentVersion(const AvailabilityDomain &domain, const ASTContext &ctx) {
switch (domain.getKind()) {
Expand Down
Loading