Skip to content

Commit d07e852

Browse files
authored
Merge pull request #79602 from tshortli/availability-spec-storage
AST: Use `AvailabilityDomainOrIdentifier` to store domains in `AvailabilitySpec`
2 parents 9298918 + c54825b commit d07e852

File tree

10 files changed

+124
-140
lines changed

10 files changed

+124
-140
lines changed

include/swift/AST/ASTBridging.h

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -705,25 +705,20 @@ BridgedAvailabilitySpec
705705
BridgedAvailabilitySpec_createWildcard(BridgedASTContext cContext,
706706
BridgedSourceLoc cLoc);
707707

708-
SWIFT_NAME(
709-
"BridgedAvailabilitySpec.createPlatformAgnostic(_:kind:nameLoc:version:"
710-
"versionRange:)")
711-
BridgedAvailabilitySpec BridgedAvailabilitySpec_createPlatformAgnostic(
712-
BridgedASTContext cContext, BridgedAvailabilitySpecKind cKind,
708+
SWIFT_NAME("BridgedAvailabilitySpec.create(_:domain:nameLoc:version:"
709+
"versionRange:)")
710+
BridgedAvailabilitySpec BridgedAvailabilitySpec_createForDomain(
711+
BridgedASTContext cContext, BridgedAvailabilityDomain cDomain,
713712
BridgedSourceLoc cLoc, BridgedVersionTuple cVersion,
714713
BridgedSourceRange cVersionRange);
715714

716-
SWIFT_NAME("BridgedAvailabilitySpec.createPlatformVersioned(_:platform:"
717-
"platformLoc:version:versionRange:)")
718-
BridgedAvailabilitySpec BridgedAvailabilitySpec_createPlatformVersioned(
719-
BridgedASTContext cContext, BridgedPlatformKind cPlatform,
720-
BridgedSourceLoc cPlatformLoc, BridgedVersionTuple cVersion,
721-
BridgedSourceRange cVersionSrcRange);
722-
723715
SWIFT_NAME("getter:BridgedAvailabilitySpec.sourceRange(self:)")
724716
BridgedSourceRange
725717
BridgedAvailabilitySpec_getSourceRange(BridgedAvailabilitySpec spec);
726718

719+
SWIFT_NAME("getter:BridgedAvailabilitySpec.isWildcard(self:)")
720+
bool BridgedAvailabilitySpec_isWildcard(BridgedAvailabilitySpec spec);
721+
727722
SWIFT_NAME("getter:BridgedAvailabilitySpec.domain(self:)")
728723
BridgedAvailabilityDomain
729724
BridgedAvailabilitySpec_getDomain(BridgedAvailabilitySpec spec);

include/swift/AST/AvailabilityDomain.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,11 @@ class AvailabilityDomain final {
247247
void Profile(llvm::FoldingSetNodeID &ID) const {
248248
ID.AddPointer(getOpaqueValue());
249249
}
250+
251+
private:
252+
friend class AvailabilityDomainOrIdentifier;
253+
254+
AvailabilityDomain copy(ASTContext &ctx) const;
250255
};
251256

252257
/// Represents an availability domain that has been defined in a module.
@@ -317,6 +322,11 @@ class AvailabilityDomainOrIdentifier {
317322
return storage.get<Identifier>();
318323
return std::nullopt;
319324
}
325+
326+
/// Creates a new `AvailabilityDomainOrIdentifier`, defensively copying
327+
/// members of the original into the given `ASTContext` in case it is
328+
/// different than the context that the original was created for.
329+
AvailabilityDomainOrIdentifier copy(ASTContext &ctx) const;
320330
};
321331

322332
} // end namespace swift

include/swift/AST/AvailabilitySpec.h

Lines changed: 29 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -30,32 +30,13 @@
3030

3131
namespace swift {
3232
class ASTContext;
33-
34-
enum class AvailabilitySpecKind {
35-
/// A platform-version constraint of the form "PlatformName X.Y.Z"
36-
PlatformVersionConstraint,
37-
38-
/// A wildcard constraint, spelled '*', that is equivalent
39-
/// to CurrentPlatformName >= MinimumDeploymentTargetVersion
40-
Wildcard,
41-
42-
/// A language-version constraint of the form "swift X.Y.Z"
43-
LanguageVersionConstraint,
44-
45-
/// A PackageDescription version constraint of the form "_PackageDescription
46-
/// X.Y.Z"
47-
PackageDescriptionVersionConstraint,
48-
};
49-
5033
class SemanticAvailabilitySpec;
5134

5235
/// The root class for specifications of API availability in availability
5336
/// queries.
5437
class AvailabilitySpec : public ASTAllocated<AvailabilitySpec> {
55-
protected:
56-
AvailabilitySpecKind Kind;
57-
58-
std::optional<AvailabilityDomain> Domain;
38+
using DomainStorage = llvm::PointerIntPair<AvailabilityDomainOrIdentifier, 1>;
39+
DomainStorage Storage;
5940

6041
/// The range of the entire spec, including the version if there is one.
6142
SourceRange SrcRange;
@@ -70,13 +51,15 @@ class AvailabilitySpec : public ASTAllocated<AvailabilitySpec> {
7051
// Location of the availability macro expanded to create this spec.
7152
SourceLoc MacroLoc;
7253

73-
AvailabilitySpec(AvailabilitySpecKind Kind,
74-
std::optional<AvailabilityDomain> Domain,
75-
SourceRange SrcRange, llvm::VersionTuple Version,
76-
SourceLoc VersionStartLoc)
77-
: Kind(Kind), Domain(Domain), SrcRange(SrcRange), Version(Version),
54+
AvailabilitySpec(DomainStorage Storage, SourceRange SrcRange,
55+
llvm::VersionTuple Version, SourceLoc VersionStartLoc)
56+
: Storage(Storage), SrcRange(SrcRange), Version(Version),
7857
VersionStartLoc(VersionStartLoc) {}
7958

59+
AvailabilityDomainOrIdentifier getDomainOrIdentifier() const {
60+
return Storage.getPointer();
61+
}
62+
8063
public:
8164
/// Creates a wildcard availability specification that guards execution
8265
/// by checking that the run-time version is greater than the minimum
@@ -89,33 +72,20 @@ class AvailabilitySpec : public ASTAllocated<AvailabilitySpec> {
8972
/// compiler will still catch references to potentially unavailable symbols.
9073
static AvailabilitySpec *createWildcard(ASTContext &ctx, SourceLoc starLoc);
9174

92-
/// Creates an availability specification that guards execution based on the
93-
/// compile-time platform agnostic version, e.g., swift >= 3.0.1,
94-
/// package-description >= 4.0.
95-
static AvailabilitySpec *createPlatformAgnostic(ASTContext &ctx,
96-
AvailabilitySpecKind kind,
97-
SourceLoc nameLoc,
75+
/// Creates an availability specification that requires a minimum version of
76+
/// some availability domain, e.g., macOS >= 10.10 or swift >= 3.0.1.
77+
static AvailabilitySpec *
78+
createForDomain(ASTContext &ctx, AvailabilityDomain domain, SourceLoc loc,
79+
llvm::VersionTuple version, SourceRange versionRange);
80+
81+
/// Creates an availability specification for an unknown availability domain.
82+
static AvailabilitySpec *createForUnknownDomain(ASTContext &ctx,
83+
Identifier domainIdentifier,
84+
SourceLoc loc,
9885
llvm::VersionTuple version,
9986
SourceRange versionRange);
10087

101-
/// Creates an availability specification that guards execution based on the
102-
/// run-time platform and version, e.g., macOS >= 10.10.
103-
static AvailabilitySpec *createPlatformVersioned(ASTContext &ctx,
104-
PlatformKind platform,
105-
SourceLoc platformLoc,
106-
llvm::VersionTuple version,
107-
SourceRange versionRange);
108-
109-
AvailabilitySpec *clone(ASTContext &ctx) const {
110-
return new (ctx)
111-
AvailabilitySpec(Kind, Domain, SrcRange, Version, VersionStartLoc);
112-
}
113-
114-
AvailabilitySpecKind getKind() const { return Kind; }
115-
116-
bool isWildcard() const {
117-
return getKind() == AvailabilitySpecKind::Wildcard;
118-
}
88+
AvailabilitySpec *clone(ASTContext &ctx) const;
11989

12090
/// Returns a type-checked representation of the spec, or `std::nullopt` if
12191
/// the spec is invalid.
@@ -125,7 +95,15 @@ class AvailabilitySpec : public ASTAllocated<AvailabilitySpec> {
12595
SourceRange getSourceRange() const { return SrcRange; }
12696
SourceLoc getStartLoc() const { return SrcRange.Start; }
12797

128-
std::optional<AvailabilityDomain> getDomain() const { return Domain; }
98+
bool isWildcard() const {
99+
if (auto domain = getDomain())
100+
return domain->isUniversal();
101+
return false;
102+
}
103+
104+
std::optional<AvailabilityDomain> getDomain() const {
105+
return getDomainOrIdentifier().getAsDomain();
106+
}
129107

130108
PlatformKind getPlatform() const {
131109
if (auto domain = getDomain())

lib/AST/AvailabilityDomain.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,22 @@ AvailabilityDomain AvailabilityDomain::getABICompatibilityDomain() const {
168168
return *this;
169169
}
170170

171+
AvailabilityDomain AvailabilityDomain::copy(ASTContext &ctx) const {
172+
switch (getKind()) {
173+
case Kind::Universal:
174+
case Kind::SwiftLanguage:
175+
case Kind::PackageDescription:
176+
case Kind::Embedded:
177+
case Kind::Platform:
178+
// These domain kinds aren't ASTContext dependent.
179+
return *this;
180+
case Kind::Custom:
181+
// To support this, the CustomAvailabilityDomain content would need to
182+
// be copied to the other context, allocating new storage if necessary.
183+
llvm::report_fatal_error("unsupported");
184+
}
185+
}
186+
171187
CustomAvailabilityDomain::CustomAvailabilityDomain(Identifier name,
172188
ModuleDecl *mod, Kind kind)
173189
: name(name), kind(kind), mod(mod) {
@@ -180,3 +196,12 @@ CustomAvailabilityDomain::create(const ASTContext &ctx, StringRef name,
180196
ModuleDecl *mod, Kind kind) {
181197
return new (ctx) CustomAvailabilityDomain(ctx.getIdentifier(name), mod, kind);
182198
}
199+
200+
AvailabilityDomainOrIdentifier
201+
AvailabilityDomainOrIdentifier::copy(ASTContext &ctx) const {
202+
if (auto identifier = getAsIdentifier())
203+
return ctx.getIdentifier(identifier->str());
204+
205+
DEBUG_ASSERT(isDomain());
206+
return getAsDomain()->copy(ctx);
207+
}

lib/AST/AvailabilitySpec.cpp

Lines changed: 19 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -24,45 +24,34 @@ using namespace swift;
2424
AvailabilitySpec *AvailabilitySpec::createWildcard(ASTContext &ctx,
2525
SourceLoc starLoc) {
2626
return new (ctx)
27-
AvailabilitySpec(AvailabilitySpecKind::Wildcard, std::nullopt, starLoc,
27+
AvailabilitySpec({AvailabilityDomain::forUniversal(), true}, starLoc,
2828
/*Version=*/{},
2929
/*VersionStartLoc=*/{});
3030
}
3131

32-
static AvailabilityDomain getDomainForSpecKind(AvailabilitySpecKind Kind) {
33-
switch (Kind) {
34-
case AvailabilitySpecKind::PlatformVersionConstraint:
35-
case AvailabilitySpecKind::Wildcard:
36-
llvm_unreachable("unexpected spec kind");
37-
case AvailabilitySpecKind::LanguageVersionConstraint:
38-
return AvailabilityDomain::forSwiftLanguage();
39-
case AvailabilitySpecKind::PackageDescriptionVersionConstraint:
40-
return AvailabilityDomain::forPackageDescription();
41-
}
32+
AvailabilitySpec *AvailabilitySpec::createForDomain(ASTContext &ctx,
33+
AvailabilityDomain domain,
34+
SourceLoc loc,
35+
llvm::VersionTuple version,
36+
SourceRange versionRange) {
37+
DEBUG_ASSERT(!version.empty());
38+
return new (ctx)
39+
AvailabilitySpec({domain, true}, SourceRange(loc, versionRange.End),
40+
version, versionRange.Start);
4241
}
4342

44-
AvailabilitySpec *AvailabilitySpec::createPlatformAgnostic(
45-
ASTContext &ctx, AvailabilitySpecKind kind, SourceLoc nameLoc,
43+
AvailabilitySpec *AvailabilitySpec::createForUnknownDomain(
44+
ASTContext &ctx, Identifier domainIdentifier, SourceLoc loc,
4645
llvm::VersionTuple version, SourceRange versionRange) {
47-
return new (ctx) AvailabilitySpec(kind, getDomainForSpecKind(kind),
48-
SourceRange(nameLoc, versionRange.End),
49-
version, versionRange.Start);
50-
}
51-
52-
static std::optional<AvailabilityDomain>
53-
getDomainForPlatform(PlatformKind Platform) {
54-
if (Platform != PlatformKind::none)
55-
return AvailabilityDomain::forPlatform(Platform);
56-
return std::nullopt;
46+
return new (ctx) AvailabilitySpec({domainIdentifier, true},
47+
SourceRange(loc, versionRange.End), version,
48+
versionRange.Start);
5749
}
5850

59-
AvailabilitySpec *AvailabilitySpec::createPlatformVersioned(
60-
ASTContext &ctx, PlatformKind platform, SourceLoc platformLoc,
61-
llvm::VersionTuple version, SourceRange versionRange) {
62-
return new (ctx) AvailabilitySpec(
63-
AvailabilitySpecKind::PlatformVersionConstraint,
64-
getDomainForPlatform(platform),
65-
SourceRange(platformLoc, versionRange.End), version, versionRange.Start);
51+
AvailabilitySpec *AvailabilitySpec::clone(ASTContext &ctx) const {
52+
return new (ctx)
53+
AvailabilitySpec({getDomainOrIdentifier().copy(ctx), true},
54+
SrcRange, Version, VersionStartLoc);
6655
}
6756

6857
llvm::VersionTuple SemanticAvailabilitySpec::getVersion() const {

lib/AST/Bridging/AvailabilityBridging.cpp

Lines changed: 8 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -86,50 +86,31 @@ static BridgedPlatformKind bridge(PlatformKind platform) {
8686
// MARK: AvailabilitySpec
8787
//===----------------------------------------------------------------------===//
8888

89-
static AvailabilitySpecKind unbridge(BridgedAvailabilitySpecKind kind) {
90-
switch (kind) {
91-
case BridgedAvailabilitySpecKindPlatformVersionConstraint:
92-
return AvailabilitySpecKind::PlatformVersionConstraint;
93-
case BridgedAvailabilitySpecKindWildcard:
94-
return AvailabilitySpecKind::Wildcard;
95-
case BridgedAvailabilitySpecKindLanguageVersionConstraint:
96-
return AvailabilitySpecKind::LanguageVersionConstraint;
97-
case BridgedAvailabilitySpecKindPackageDescriptionVersionConstraint:
98-
return AvailabilitySpecKind::PackageDescriptionVersionConstraint;
99-
}
100-
llvm_unreachable("unhandled enum value");
101-
}
102-
10389
BridgedAvailabilitySpec
10490
BridgedAvailabilitySpec_createWildcard(BridgedASTContext cContext,
10591
BridgedSourceLoc cLoc) {
10692
return AvailabilitySpec::createWildcard(cContext.unbridged(),
10793
cLoc.unbridged());
10894
}
10995

110-
BridgedAvailabilitySpec BridgedAvailabilitySpec_createPlatformAgnostic(
111-
BridgedASTContext cContext, BridgedAvailabilitySpecKind cKind,
96+
BridgedAvailabilitySpec BridgedAvailabilitySpec_createForDomain(
97+
BridgedASTContext cContext, BridgedAvailabilityDomain cDomain,
11298
BridgedSourceLoc cLoc, BridgedVersionTuple cVersion,
11399
BridgedSourceRange cVersionRange) {
114-
return AvailabilitySpec::createPlatformAgnostic(
115-
cContext.unbridged(), unbridge(cKind), cLoc.unbridged(),
100+
return AvailabilitySpec::createForDomain(
101+
cContext.unbridged(), cDomain.unbridged(), cLoc.unbridged(),
116102
cVersion.unbridged(), cVersionRange.unbridged());
117103
}
118104

119-
BridgedAvailabilitySpec BridgedAvailabilitySpec_createPlatformVersioned(
120-
BridgedASTContext cContext, BridgedPlatformKind cPlatform,
121-
BridgedSourceLoc cPlatformLoc, BridgedVersionTuple cVersion,
122-
BridgedSourceRange cVersionSrcRange) {
123-
return AvailabilitySpec::createPlatformVersioned(
124-
cContext.unbridged(), unbridge(cPlatform), cPlatformLoc.unbridged(),
125-
cVersion.unbridged(), cVersionSrcRange.unbridged());
126-
}
127-
128105
BridgedSourceRange
129106
BridgedAvailabilitySpec_getSourceRange(BridgedAvailabilitySpec spec) {
130107
return spec.unbridged()->getSourceRange();
131108
}
132109

110+
bool BridgedAvailabilitySpec_isWildcard(BridgedAvailabilitySpec spec) {
111+
return spec.unbridged()->isWildcard();
112+
}
113+
133114
BridgedAvailabilityDomain
134115
BridgedAvailabilitySpec_getDomain(BridgedAvailabilitySpec spec) {
135116
auto domain = spec.unbridged()->getDomain();

lib/ASTGen/Sources/ASTGen/Availability.swift

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ extension ASTGenVisitor {
7272

7373
var result: [BridgedAvailableAttr] = []
7474
for spec in specs {
75+
guard !spec.isWildcard else {
76+
continue
77+
}
7578
let domain = spec.domain
7679
guard !domain.isNull() else {
7780
continue
@@ -287,13 +290,13 @@ extension ASTGenVisitor {
287290

288291
switch domainNode.rawText {
289292
case "swift", "_PackageVersion":
290-
let kind: BridgedAvailabilitySpecKind = domainNode.rawText == "swift"
291-
? .languageVersionConstraint
292-
: .packageDescriptionVersionConstraint
293+
let domain: BridgedAvailabilityDomain = domainNode.rawText == "swift"
294+
? .forSwiftLanguage()
295+
: .forPackageDescription()
293296

294-
let spec = BridgedAvailabilitySpec.createPlatformAgnostic(
297+
let spec = BridgedAvailabilitySpec.create(
295298
self.ctx,
296-
kind: kind,
299+
domain: domain,
297300
nameLoc: nameLoc,
298301
version: version?.bridged ?? BridgedVersionTuple(),
299302
versionRange: versionRange
@@ -329,10 +332,10 @@ extension ASTGenVisitor {
329332
// TODO: Diagnostics.
330333
fatalError("expected version")
331334
}
332-
let spec = BridgedAvailabilitySpec.createPlatformVersioned(
335+
let spec = BridgedAvailabilitySpec.create(
333336
self.ctx,
334-
platform: platform,
335-
platformLoc: nameLoc,
337+
domain: BridgedAvailabilityDomain.forPlatform(platform),
338+
nameLoc: nameLoc,
336339
version: version.bridged,
337340
versionRange: versionRange
338341
)

0 commit comments

Comments
 (0)