Skip to content

AST: Retire subclasses of AvailabilitySpec #79354

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 3 commits into from
Feb 13, 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
60 changes: 21 additions & 39 deletions include/swift/AST/ASTBridging.h
Original file line number Diff line number Diff line change
Expand Up @@ -626,13 +626,33 @@ struct BridgedAvailabilityMacroDefinition {

enum ENUM_EXTENSIBILITY_ATTR(closed) BridgedAvailabilitySpecKind {
BridgedAvailabilitySpecKindPlatformVersionConstraint,
BridgedAvailabilitySpecKindOtherPlatform,
BridgedAvailabilitySpecKindWildcard,
BridgedAvailabilitySpecKindLanguageVersionConstraint,
BridgedAvailabilitySpecKindPackageDescriptionVersionConstraint,
};

struct BridgedAvailabilityDomain;

SWIFT_NAME("BridgedAvailabilitySpec.createWildcard(_:loc:)")
BridgedAvailabilitySpec
BridgedAvailabilitySpec_createWildcard(BridgedASTContext cContext,
BridgedSourceLoc cLoc);

SWIFT_NAME(
"BridgedAvailabilitySpec.createPlatformAgnostic(_:kind:nameLoc:version:"
"versionRange:)")
BridgedAvailabilitySpec BridgedAvailabilitySpec_createPlatformAgnostic(
BridgedASTContext cContext, BridgedAvailabilitySpecKind cKind,
BridgedSourceLoc cLoc, BridgedVersionTuple cVersion,
BridgedSourceRange cVersionRange);

SWIFT_NAME("BridgedAvailabilitySpec.createPlatformVersioned(_:platform:"
"platformLoc:version:versionRange:)")
BridgedAvailabilitySpec BridgedAvailabilitySpec_createPlatformVersioned(
BridgedASTContext cContext, BridgedPlatformKind cPlatform,
BridgedSourceLoc cPlatformLoc, BridgedVersionTuple cVersion,
BridgedSourceRange cVersionSrcRange);

SWIFT_NAME("getter:BridgedAvailabilitySpec.sourceRange(self:)")
BridgedSourceRange
BridgedAvailabilitySpec_getSourceRange(BridgedAvailabilitySpec spec);
Expand All @@ -653,44 +673,6 @@ SWIFT_NAME("getter:BridgedAvailabilitySpec.versionRange(self:)")
BridgedSourceRange
BridgedAvailabilitySpec_getVersionRange(BridgedAvailabilitySpec spec);

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

SWIFT_NAME("BridgedPlatformAgnosticVersionConstraintAvailabilitySpec."
"createParsed(_:kind:nameLoc:version:versionRange:)")
BridgedPlatformAgnosticVersionConstraintAvailabilitySpec
BridgedPlatformAgnosticVersionConstraintAvailabilitySpec_createParsed(
BridgedASTContext cContext, BridgedAvailabilitySpecKind cKind,
BridgedSourceLoc cNameLoc, BridgedVersionTuple cVersion,
BridgedSourceRange cVersionSrcRange);

SWIFT_NAME("BridgedOtherPlatformAvailabilitySpec.createParsed(_:loc:)")
BridgedOtherPlatformAvailabilitySpec
BridgedOtherPlatformAvailabilitySpec_createParsed(BridgedASTContext cContext,
BridgedSourceLoc cLoc);

SWIFT_NAME("getter:BridgedPlatformVersionConstraintAvailabilitySpec."
"asAvailabilitySpec(self:)")
BridgedAvailabilitySpec
BridgedPlatformVersionConstraintAvailabilitySpec_asAvailabilitySpec(
BridgedPlatformVersionConstraintAvailabilitySpec spec);

SWIFT_NAME("getter:BridgedPlatformAgnosticVersionConstraintAvailabilitySpec."
"asAvailabilitySpec(self:)")
BridgedAvailabilitySpec
BridgedPlatformAgnosticVersionConstraintAvailabilitySpec_asAvailabilitySpec(
BridgedPlatformAgnosticVersionConstraintAvailabilitySpec spec);

SWIFT_NAME(
"getter:BridgedOtherPlatformAvailabilitySpec.asAvailabilitySpec(self:)")
BridgedAvailabilitySpec BridgedOtherPlatformAvailabilitySpec_asAvailabilitySpec(
BridgedOtherPlatformAvailabilitySpec spec);

struct BridgedAvailabilityDomain {
void *_Nullable opaque;

Expand Down
3 changes: 0 additions & 3 deletions include/swift/AST/ASTBridgingWrappers.def
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,6 @@ AST_BRIDGING_WRAPPER_NONNULL(TypeAttributes)
AST_BRIDGING_WRAPPER_NONNULL(CustomAttribute)
AST_BRIDGING_WRAPPER_NULLABLE(ArgumentList)
AST_BRIDGING_WRAPPER_NULLABLE(AvailabilitySpec)
AST_BRIDGING_WRAPPER_NULLABLE(PlatformVersionConstraintAvailabilitySpec)
AST_BRIDGING_WRAPPER_NULLABLE(PlatformAgnosticVersionConstraintAvailabilitySpec)
AST_BRIDGING_WRAPPER_NULLABLE(OtherPlatformAvailabilitySpec)
AST_BRIDGING_WRAPPER_CONST_NONNULL(AvailabilityMacroMap)
AST_BRIDGING_WRAPPER_NONNULL(PoundAvailableInfo)

Expand Down
176 changes: 51 additions & 125 deletions include/swift/AST/AvailabilitySpec.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,19 @@ namespace swift {
class ASTContext;

enum class AvailabilitySpecKind {
/// A platform-version constraint of the form "PlatformName X.Y.Z"
PlatformVersionConstraint,
/// A platform-version constraint of the form "PlatformName X.Y.Z"
PlatformVersionConstraint,

/// A wildcard constraint, spelled '*', that is equivalent
/// to CurrentPlatformName >= MinimumDeploymentTargetVersion
OtherPlatform,
/// A wildcard constraint, spelled '*', that is equivalent
/// to CurrentPlatformName >= MinimumDeploymentTargetVersion
Wildcard,

/// A language-version constraint of the form "swift X.Y.Z"
LanguageVersionConstraint,
/// A language-version constraint of the form "swift X.Y.Z"
LanguageVersionConstraint,

/// A PackageDescription version constraint of the form "_PackageDescription X.Y.Z"
PackageDescriptionVersionConstraint,
/// A PackageDescription version constraint of the form "_PackageDescription
/// X.Y.Z"
PackageDescriptionVersionConstraint,
};

/// The root class for specifications of API availability in availability
Expand All @@ -65,16 +66,51 @@ class AvailabilitySpec : public ASTAllocated<AvailabilitySpec> {
// Location of the availability macro expanded to create this spec.
SourceLoc MacroLoc;

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

public:
/// Creates a wildcard availability specification that guards execution
/// by checking that the run-time version is greater than the minimum
/// deployment target. This specification is designed to ease porting
/// to new platforms. Because new platforms typically branch from
/// existing platforms, the wildcard allows an #available() check to do the
/// "right" thing (executing the guarded branch) on the new platform without
/// requiring a modification to every availability guard in the program. Note
/// that we still do compile-time availability checking with '*', so the
/// compiler will still catch references to potentially unavailable symbols.
static AvailabilitySpec *createWildcard(ASTContext &ctx, SourceLoc starLoc);

/// Creates an availability specification that guards execution based on the
/// compile-time platform agnostic version, e.g., swift >= 3.0.1,
/// package-description >= 4.0.
static AvailabilitySpec *createPlatformAgnostic(ASTContext &ctx,
AvailabilitySpecKind kind,
SourceLoc nameLoc,
llvm::VersionTuple version,
SourceRange versionRange);

/// Creates an availability specification that guards execution based on the
/// run-time platform and version, e.g., macOS >= 10.10.
static AvailabilitySpec *createPlatformVersioned(ASTContext &ctx,
PlatformKind platform,
SourceLoc platformLoc,
llvm::VersionTuple version,
SourceRange versionRange);

AvailabilitySpec *clone(ASTContext &ctx) const {
return new (ctx)
AvailabilitySpec(Kind, Domain, SrcRange, Version, VersionStartLoc);
}

AvailabilitySpecKind getKind() const { return Kind; }

bool isWildcard() { return getKind() == AvailabilitySpecKind::Wildcard; }

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

Expand All @@ -89,6 +125,11 @@ class AvailabilitySpec : public ASTAllocated<AvailabilitySpec> {
// The platform version to compare against.
llvm::VersionTuple getVersion() const;

// 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 Version; }

SourceRange getVersionSrcRange() const {
if (!VersionStartLoc)
return SourceRange();
Expand All @@ -100,121 +141,6 @@ class AvailabilitySpec : public ASTAllocated<AvailabilitySpec> {
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 {
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,
SourceRange 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;

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

static bool classof(const AvailabilitySpec *Spec) {
return Spec->getKind() == AvailabilitySpecKind::PlatformVersionConstraint;
}

void *
operator new(size_t Bytes, ASTContext &C,
unsigned Alignment = alignof(PlatformVersionConstraintAvailabilitySpec)){
return AvailabilitySpec::operator new(Bytes, C, AllocationArena::Permanent,
Alignment);
}
};

/// 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 {

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, getDomainForSpecKind(AvailabilitySpecKind),
SourceRange(PlatformAgnosticNameLoc, VersionSrcRange.End), Version,
VersionSrcRange.Start) {
assert(AvailabilitySpecKind == AvailabilitySpecKind::LanguageVersionConstraint ||
AvailabilitySpecKind == AvailabilitySpecKind::PackageDescriptionVersionConstraint);
}

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

static bool classof(const AvailabilitySpec *Spec) {
return Spec->getKind() == AvailabilitySpecKind::LanguageVersionConstraint ||
Spec->getKind() == AvailabilitySpecKind::PackageDescriptionVersionConstraint;
}

void *
operator new(size_t Bytes, ASTContext &C,
unsigned Alignment = alignof(PlatformAgnosticVersionConstraintAvailabilitySpec)){
return AvailabilitySpec::operator new(Bytes, C, AllocationArena::Permanent,
Alignment);
}
};

/// A wildcard availability specification that guards execution
/// by checking that the run-time version is greater than the minimum
/// deployment target. This specification is designed to ease porting
/// to new platforms. Because new platforms typically branch from
/// existing platforms, the wildcard allows an #available() check to do the
/// "right" thing (executing the guarded branch) on the new platform without
/// requiring a modification to every availability guard in the program. Note
/// that we still do compile-time availability checking with '*', so the
/// compiler will still catch references to potentially unavailable symbols.
class OtherPlatformAvailabilitySpec : public AvailabilitySpec {
public:
OtherPlatformAvailabilitySpec(SourceLoc StarLoc)
: AvailabilitySpec(AvailabilitySpecKind::OtherPlatform, std::nullopt,
StarLoc,
/*Version=*/{},
/*VersionStartLoc=*/{}) {}

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

static bool classof(const AvailabilitySpec *Spec) {
return Spec->getKind() == AvailabilitySpecKind::OtherPlatform;
}

void *
operator new(size_t Bytes, ASTContext &C,
unsigned Alignment = alignof(OtherPlatformAvailabilitySpec)) {
return AvailabilitySpec::operator new(Bytes, C, AllocationArena::Permanent,
Alignment);
}
};

/// Maps of macro name and version to availability specifications.
/// Organized as two nested \c DenseMap keyed first on the macro name then
/// the macro version. This structure allows to peek at macro names before
Expand Down
8 changes: 3 additions & 5 deletions include/swift/AST/ConstTypeInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,7 @@ class BuilderValue : public CompileTimeValue {
class ConditionalMember : public BuilderMember {
public:
ConditionalMember(MemberKind MemberKind,
std::vector<PlatformVersionConstraintAvailabilitySpec>
AvailabilityAttributes,
std::vector<AvailabilitySpec> AvailabilityAttributes,
std::vector<std::shared_ptr<BuilderMember>> IfElements,
std::vector<std::shared_ptr<BuilderMember>> ElseElements)
: BuilderMember(MemberKind),
Expand All @@ -239,7 +238,7 @@ class BuilderValue : public CompileTimeValue {
(Kind == MemberKind::Optional);
}

std::optional<std::vector<PlatformVersionConstraintAvailabilitySpec>>
std::optional<std::vector<AvailabilitySpec>>
getAvailabilityAttributes() const {
return AvailabilityAttributes;
}
Expand All @@ -251,8 +250,7 @@ class BuilderValue : public CompileTimeValue {
}

private:
std::optional<std::vector<PlatformVersionConstraintAvailabilitySpec>>
AvailabilityAttributes;
std::optional<std::vector<AvailabilitySpec>> AvailabilityAttributes;
std::vector<std::shared_ptr<BuilderMember>> IfElements;
std::vector<std::shared_ptr<BuilderMember>> ElseElements;
};
Expand Down
9 changes: 3 additions & 6 deletions include/swift/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ namespace llvm {
}

namespace swift {
class AvailabilitySpec;
class CodeCompletionCallbacks;
class DoneParsingCallback;
class DefaultArgumentInitializer;
Expand All @@ -53,8 +54,6 @@ namespace swift {
class SILParserStateBase;
class SourceManager;
class UUID;
class PlatformVersionConstraintAvailabilitySpec;
class PlatformAgnosticVersionConstraintAvailabilitySpec;

struct EnumElementInfo;

Expand Down Expand Up @@ -2058,10 +2057,8 @@ class Parser {
SmallVectorImpl<AvailabilitySpec *> &Specs);

ParserResult<AvailabilitySpec> parseAvailabilitySpec();
ParserResult<PlatformVersionConstraintAvailabilitySpec>
parsePlatformVersionConstraintSpec();
ParserResult<PlatformAgnosticVersionConstraintAvailabilitySpec>
parsePlatformAgnosticVersionConstraintSpec();
ParserResult<AvailabilitySpec> parsePlatformVersionConstraintSpec();
ParserResult<AvailabilitySpec> parsePlatformAgnosticVersionConstraintSpec();
bool
parseAvailability(bool parseAsPartOfSpecializeAttr, StringRef AttrName,
bool &DiscardAttribute, SourceRange &attrRange,
Expand Down
Loading