Skip to content

AST: Begin refactoring AvailabilitySpec to support custom domains #79312

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 4 commits into from
Feb 12, 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/ASTBridging.h
Original file line number Diff line number Diff line change
Expand Up @@ -654,12 +654,12 @@ BridgedSourceRange
BridgedAvailabilitySpec_getVersionRange(BridgedAvailabilitySpec spec);

SWIFT_NAME("BridgedPlatformVersionConstraintAvailabilitySpec.createParsed(_:"
"platform:platformLoc:version:runtimeVersion:versionRange:)")
"platform:platformLoc:version:versionRange:)")
BridgedPlatformVersionConstraintAvailabilitySpec
BridgedPlatformVersionConstraintAvailabilitySpec_createParsed(
BridgedASTContext cContext, BridgedPlatformKind cPlatform,
BridgedSourceLoc cPlatformLoc, BridgedVersionTuple cVersion,
BridgedVersionTuple cRuntimeVersion, BridgedSourceRange cVersionSrcRange);
BridgedSourceRange cVersionSrcRange);

SWIFT_NAME("BridgedPlatformAgnosticVersionConstraintAvailabilitySpec."
"createParsed(_:kind:nameLoc:version:versionRange:)")
Expand Down
160 changes: 74 additions & 86 deletions include/swift/AST/AvailabilitySpec.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#define SWIFT_AST_AVAILABILITY_SPEC_H

#include "swift/AST/ASTAllocated.h"
#include "swift/AST/AvailabilityDomain.h"
#include "swift/AST/Identifier.h"
#include "swift/AST/PlatformKind.h"
#include "swift/Basic/SourceLoc.h"
Expand All @@ -27,9 +28,6 @@

namespace swift {
class ASTContext;
class AvailabilityDomain;

enum class VersionComparison { GreaterThanEqual };

enum class AvailabilitySpecKind {
/// A platform-version constraint of the form "PlatformName X.Y.Z"
Expand All @@ -49,86 +47,82 @@ enum class AvailabilitySpecKind {
/// The root class for specifications of API availability in availability
/// queries.
class AvailabilitySpec : public ASTAllocated<AvailabilitySpec> {
protected:
AvailabilitySpecKind Kind;

std::optional<AvailabilityDomain> Domain;

/// The range of the entire spec, including the version if there is one.
SourceRange SrcRange;

/// The version (may be empty if there was no version specified).
llvm::VersionTuple Version;

/// If there is a version specified, this is its start location within the
/// overall source range.
SourceLoc VersionStartLoc;

// Location of the availability macro expanded to create this spec.
SourceLoc MacroLoc;

public:
AvailabilitySpec(AvailabilitySpecKind Kind) : Kind(Kind) {}
AvailabilitySpec(AvailabilitySpecKind Kind,
std::optional<AvailabilityDomain> Domain,
SourceRange SrcRange, llvm::VersionTuple Version,
SourceLoc VersionStartLoc)
: Kind(Kind), Domain(Domain), SrcRange(SrcRange), Version(Version),
VersionStartLoc(VersionStartLoc) {}

AvailabilitySpecKind getKind() const { return Kind; }

SourceRange getSourceRange() const;
SourceRange getSourceRange() const { return SrcRange; }
SourceLoc getStartLoc() const { return SrcRange.Start; }

std::optional<AvailabilityDomain> getDomain() const;
std::optional<AvailabilityDomain> getDomain() const { return Domain; }

std::optional<PlatformKind> getPlatform() const;
PlatformKind getPlatform() const {
if (auto domain = getDomain())
return domain->getPlatformKind();
return PlatformKind::none;
}

// The platform version to compare against.
llvm::VersionTuple getVersion() const;

SourceRange getVersionSrcRange() const;
SourceRange getVersionSrcRange() const {
if (!VersionStartLoc)
return SourceRange();
return SourceRange(VersionStartLoc, SrcRange.End);
}

// Location of the macro expanded to create this spec.
SourceLoc getMacroLoc() const { return MacroLoc; }
void setMacroLoc(SourceLoc loc) { MacroLoc = loc; }
};

/// An availability specification that guards execution based on the
/// run-time platform and version, e.g., OS X >= 10.10.
class PlatformVersionConstraintAvailabilitySpec : public AvailabilitySpec {
PlatformKind Platform;
SourceLoc PlatformLoc;

llvm::VersionTuple Version;

// For macOS Big Sur, we canonicalize 10.16 to 11.0 for compile-time
// checking since clang canonicalizes availability markup. However, to
// support Beta versions of macOS Big Sur where the OS
// reports 10.16 at run time, we need to compare against 10.16,
//
// This means for:
//
// if #available(macOS 10.16, *) { ... }
//
// we need to keep around both a canonical version for use in compile-time
// checks and an uncanonicalized version for the version to actually codegen
// with.
llvm::VersionTuple RuntimeVersion;

SourceRange VersionSrcRange;

// Location of the macro expanded to create this spec.
SourceLoc MacroLoc;
static std::optional<AvailabilityDomain>
getDomainForPlatform(PlatformKind Platform) {
if (Platform != PlatformKind::none)
return AvailabilityDomain::forPlatform(Platform);
return std::nullopt;
}

public:
PlatformVersionConstraintAvailabilitySpec(PlatformKind Platform,
SourceLoc PlatformLoc,
llvm::VersionTuple Version,
llvm::VersionTuple RuntimeVersion,
SourceRange VersionSrcRange)
: AvailabilitySpec(AvailabilitySpecKind::PlatformVersionConstraint),
Platform(Platform),
PlatformLoc(PlatformLoc), Version(Version),
RuntimeVersion(RuntimeVersion),
VersionSrcRange(VersionSrcRange) {}

/// The required platform.
PlatformKind getPlatform() const { return Platform; }
SourceLoc getPlatformLoc() const { return PlatformLoc; }

/// Returns true when the constraint is for a platform that was not
/// recognized. This enables better recovery during parsing but should never
/// be true after parsing is completed.
bool isUnrecognizedPlatform() const { return Platform == PlatformKind::none; }

// The platform version to compare against.
llvm::VersionTuple getVersion() const { return Version; }
SourceRange getVersionSrcRange() const { return VersionSrcRange; }

: AvailabilitySpec(AvailabilitySpecKind::PlatformVersionConstraint,
getDomainForPlatform(Platform),
SourceRange(PlatformLoc, VersionSrcRange.End), Version,
VersionSrcRange.Start) {}
// The version to be used in codegen for version comparisons at run time.
// This is required to support beta versions of macOS Big Sur that
// report 10.16 at run time.
llvm::VersionTuple getRuntimeVersion() const { return RuntimeVersion; }

SourceRange getSourceRange() const;

// Location of the macro expanded to create this spec.
SourceLoc getMacroLoc() const { return MacroLoc; }
void setMacroLoc(SourceLoc loc) { MacroLoc = loc; }
llvm::VersionTuple getRuntimeVersion() const;

void print(raw_ostream &OS, unsigned Indent) const;

Expand All @@ -147,36 +141,34 @@ class PlatformVersionConstraintAvailabilitySpec : public AvailabilitySpec {
/// An availability specification that guards execution based on the
/// compile-time platform agnostic version, e.g., swift >= 3.0.1,
/// package-description >= 4.0.
class PlatformAgnosticVersionConstraintAvailabilitySpec : public AvailabilitySpec {
SourceLoc PlatformAgnosticNameLoc;

llvm::VersionTuple Version;
SourceRange VersionSrcRange;
class PlatformAgnosticVersionConstraintAvailabilitySpec
: public AvailabilitySpec {

static AvailabilityDomain getDomainForSpecKind(AvailabilitySpecKind Kind) {
switch (Kind) {
case AvailabilitySpecKind::PlatformVersionConstraint:
case AvailabilitySpecKind::OtherPlatform:
llvm_unreachable("unexpected spec kind");
case AvailabilitySpecKind::LanguageVersionConstraint:
return AvailabilityDomain::forSwiftLanguage();
case AvailabilitySpecKind::PackageDescriptionVersionConstraint:
return AvailabilityDomain::forPackageDescription();
}
}

public:
PlatformAgnosticVersionConstraintAvailabilitySpec(
AvailabilitySpecKind AvailabilitySpecKind,
SourceLoc PlatformAgnosticNameLoc, llvm::VersionTuple Version,
SourceRange VersionSrcRange)
: AvailabilitySpec(AvailabilitySpecKind),
PlatformAgnosticNameLoc(PlatformAgnosticNameLoc), Version(Version),
VersionSrcRange(VersionSrcRange) {
: AvailabilitySpec(
AvailabilitySpecKind, getDomainForSpecKind(AvailabilitySpecKind),
SourceRange(PlatformAgnosticNameLoc, VersionSrcRange.End), Version,
VersionSrcRange.Start) {
assert(AvailabilitySpecKind == AvailabilitySpecKind::LanguageVersionConstraint ||
AvailabilitySpecKind == AvailabilitySpecKind::PackageDescriptionVersionConstraint);
}

SourceLoc getPlatformAgnosticNameLoc() const { return PlatformAgnosticNameLoc; }

// The platform version to compare against.
llvm::VersionTuple getVersion() const { return Version; }
SourceRange getVersionSrcRange() const { return VersionSrcRange; }

SourceRange getSourceRange() const;

bool isLanguageVersionSpecific() const {
return getKind() == AvailabilitySpecKind::LanguageVersionConstraint;
}

void print(raw_ostream &OS, unsigned Indent) const;

static bool classof(const AvailabilitySpec *Spec) {
Expand All @@ -202,16 +194,12 @@ class PlatformAgnosticVersionConstraintAvailabilitySpec : public AvailabilitySpe
/// that we still do compile-time availability checking with '*', so the
/// compiler will still catch references to potentially unavailable symbols.
class OtherPlatformAvailabilitySpec : public AvailabilitySpec {
SourceLoc StarLoc;

public:
OtherPlatformAvailabilitySpec(SourceLoc StarLoc)
: AvailabilitySpec(AvailabilitySpecKind::OtherPlatform),
StarLoc(StarLoc) {}

SourceLoc getStarLoc() const { return StarLoc; }

SourceRange getSourceRange() const { return SourceRange(StarLoc, StarLoc); }
: AvailabilitySpec(AvailabilitySpecKind::OtherPlatform, std::nullopt,
StarLoc,
/*Version=*/{},
/*VersionStartLoc=*/{}) {}

void print(raw_ostream &OS, unsigned Indent) const;

Expand Down
1 change: 1 addition & 0 deletions include/swift/AST/ConstTypeInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#define SWIFT_AST_CONST_TYPE_INFO_H

#include "swift/AST/Attr.h"
#include "swift/AST/AvailabilitySpec.h"
#include "swift/AST/Type.h"
#include "swift/AST/TypeCheckRequests.h"
#include <memory>
Expand Down
2 changes: 1 addition & 1 deletion include/swift/AST/Stmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
#include "swift/AST/ASTAllocated.h"
#include "swift/AST/ASTNode.h"
#include "swift/AST/AvailabilityRange.h"
#include "swift/AST/AvailabilitySpec.h"
#include "swift/AST/ConcreteDeclRef.h"
#include "swift/AST/IfConfigClause.h"
#include "swift/AST/ThrownErrorDestination.h"
Expand All @@ -36,6 +35,7 @@ namespace swift {
class AnyPattern;
class ASTContext;
class ASTWalker;
class AvailabilitySpec;
class Decl;
class DeclContext;
class Evaluator;
Expand Down
4 changes: 3 additions & 1 deletion include/swift/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ namespace swift {
class SILParserStateBase;
class SourceManager;
class UUID;

class PlatformVersionConstraintAvailabilitySpec;
class PlatformAgnosticVersionConstraintAvailabilitySpec;

struct EnumElementInfo;

/// Different contexts in which BraceItemList are parsed.
Expand Down
3 changes: 2 additions & 1 deletion lib/AST/ASTDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "swift/AST/ASTVisitor.h"
#include "swift/AST/Attr.h"
#include "swift/AST/AutoDiff.h"
#include "swift/AST/AvailabilitySpec.h"
#include "swift/AST/ClangModuleLoader.h"
#include "swift/AST/ForeignAsyncConvention.h"
#include "swift/AST/ForeignErrorConvention.h"
Expand Down Expand Up @@ -1117,7 +1118,7 @@ namespace {
printHead("platform_agnostic_version_constraint_"
"availability_spec",
PatternColor, label);
printField(agnostic->isLanguageVersionSpecific()
printField(agnostic->getDomain()->isSwiftLanguage()
? "swift"
: "package_description",
Label::always("kind"));
Expand Down
1 change: 1 addition & 0 deletions lib/AST/AvailabilityScope.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#include "swift/AST/ASTContext.h"
#include "swift/AST/AvailabilityInference.h"
#include "swift/AST/AvailabilitySpec.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Expr.h"
#include "swift/AST/Module.h"
Expand Down
Loading