Skip to content

Commit 7a85bd3

Browse files
committed
AST: Introduce a Custom availability domain kind.
1 parent 43f2c03 commit 7a85bd3

File tree

4 files changed

+96
-6
lines changed

4 files changed

+96
-6
lines changed

include/swift/AST/AvailabilityDomain.h

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#ifndef SWIFT_AST_AVAILABILITY_DOMAIN_H
1919
#define SWIFT_AST_AVAILABILITY_DOMAIN_H
2020

21+
#include "swift/AST/ASTAllocated.h"
22+
#include "swift/AST/Identifier.h"
2123
#include "swift/AST/PlatformKind.h"
2224
#include "swift/Basic/LLVM.h"
2325
#include "llvm/ADT/FoldingSet.h"
@@ -26,7 +28,9 @@
2628

2729
namespace swift {
2830
class ASTContext;
31+
class CustomAvailabilityDomain;
2932
class DeclContext;
33+
class ModuleDecl;
3034

3135
/// Represents a dimension of availability (e.g. macOS platform or Swift
3236
/// language mode).
@@ -48,6 +52,10 @@ class AvailabilityDomain final {
4852

4953
/// Represents availability for a specific operating system platform.
5054
Platform,
55+
56+
/// Represents availability for an arbitrary domain that is defined at
57+
/// compile time by a module.
58+
Custom,
5159
};
5260

5361
private:
@@ -86,13 +94,10 @@ class AvailabilityDomain final {
8694
PlatformKind getPlatform() { return platform; }
8795
};
8896

89-
/// This will eventually be a class storing information about externally
90-
/// defined availability domains.
91-
using ExternalDomain = void;
92-
9397
using InlineDomainPtr =
9498
llvm::PointerEmbeddedInt<uint32_t, InlineDomain::ReprBits>;
95-
using Storage = llvm::PointerUnion<ExternalDomain *, InlineDomainPtr>;
99+
using Storage =
100+
llvm::PointerUnion<CustomAvailabilityDomain *, InlineDomainPtr>;
96101
Storage storage;
97102

98103
AvailabilityDomain(Kind kind)
@@ -103,6 +108,8 @@ class AvailabilityDomain final {
103108
AvailabilityDomain(PlatformKind platform)
104109
: storage(InlineDomain(Kind::Platform, platform).asInteger()) {};
105110

111+
AvailabilityDomain(CustomAvailabilityDomain *domain) : storage(domain) {};
112+
106113
AvailabilityDomain(Storage storage) : storage(storage) {};
107114

108115
static AvailabilityDomain fromOpaque(void *opaque) {
@@ -118,6 +125,11 @@ class AvailabilityDomain final {
118125
: std::nullopt;
119126
}
120127

128+
CustomAvailabilityDomain *getCustomDomain() const {
129+
assert(isCustom());
130+
return storage.get<CustomAvailabilityDomain *>();
131+
}
132+
121133
public:
122134
AvailabilityDomain() {}
123135

@@ -141,6 +153,10 @@ class AvailabilityDomain final {
141153
return AvailabilityDomain(Kind::Embedded);
142154
}
143155

156+
static AvailabilityDomain forCustom(CustomAvailabilityDomain *domain) {
157+
return AvailabilityDomain(domain);
158+
}
159+
144160
/// Returns the built-in availability domain identified by the given string.
145161
static std::optional<AvailabilityDomain>
146162
builtinDomainForString(StringRef string, const DeclContext *declContext);
@@ -149,7 +165,7 @@ class AvailabilityDomain final {
149165
if (auto inlineDomain = getInlineDomain())
150166
return inlineDomain->getKind();
151167

152-
llvm_unreachable("unimplemented");
168+
return Kind::Custom;
153169
}
154170

155171
bool isUniversal() const { return getKind() == Kind::Universal; }
@@ -164,6 +180,8 @@ class AvailabilityDomain final {
164180

165181
bool isEmbedded() const { return getKind() == Kind::Embedded; }
166182

183+
bool isCustom() const { return getKind() == Kind::Custom; }
184+
167185
/// Returns the platform kind for this domain if applicable.
168186
PlatformKind getPlatformKind() const {
169187
if (auto inlineDomain = getInlineDomain())
@@ -183,6 +201,9 @@ class AvailabilityDomain final {
183201
/// Returns the string to use when printing an `@available` attribute.
184202
llvm::StringRef getNameForAttributePrinting() const;
185203

204+
/// Returns the module that the domain belongs to, if it is a custom domain.
205+
ModuleDecl *getModule() const;
206+
186207
/// Returns true if availability in `other` is a subset of availability in
187208
/// this domain. The set of all availability domains form a lattice where the
188209
/// universal domain (`*`) is the bottom element.
@@ -201,6 +222,34 @@ class AvailabilityDomain final {
201222
}
202223
};
203224

225+
/// Represents an availability domain that has been defined in a module.
226+
class CustomAvailabilityDomain : public ASTAllocated<CustomAvailabilityDomain> {
227+
public:
228+
enum class Kind {
229+
/// A domain that is known to be enabled at compile time.
230+
Enabled,
231+
/// A domain that is known to be disabled at compile time.
232+
Disabled,
233+
/// A domain with an enablement state that must be queried at runtime.
234+
Dynamic,
235+
};
236+
237+
private:
238+
Identifier name;
239+
Kind kind;
240+
ModuleDecl *mod;
241+
242+
CustomAvailabilityDomain(Identifier name, ModuleDecl *mod, Kind kind);
243+
244+
public:
245+
static CustomAvailabilityDomain *create(const ASTContext &ctx, StringRef name,
246+
ModuleDecl *mod, Kind kind);
247+
248+
Identifier getName() const { return name; }
249+
Kind getKind() const { return kind; }
250+
ModuleDecl *getModule() const { return mod; }
251+
};
252+
204253
} // end namespace swift
205254

206255
namespace llvm {

lib/AST/Availability.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,15 @@ void AvailabilityInference::applyInferredAvailableAttrs(
221221
return false;
222222
case AvailabilityDomain::Kind::Platform:
223223
return domain.getPlatformKind() < other.domain.getPlatformKind();
224+
case AvailabilityDomain::Kind::Custom: {
225+
auto mod = domain.getModule();
226+
auto otherMod = other.domain.getModule();
227+
if (mod != otherMod)
228+
return mod->getName() < otherMod->getName();
229+
230+
return domain.getNameForAttributePrinting() <
231+
other.domain.getNameForAttributePrinting();
232+
}
224233
}
225234
}
226235
};

lib/AST/AvailabilityDomain.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "swift/AST/AvailabilityDomain.h"
1414
#include "swift/AST/ASTContext.h"
1515
#include "swift/AST/Decl.h"
16+
#include "swift/Basic/Assertions.h"
1617
#include "llvm/ADT/StringSwitch.h"
1718

1819
using namespace swift;
@@ -48,6 +49,10 @@ bool AvailabilityDomain::isActive(const ASTContext &ctx) const {
4849
return true;
4950
case Kind::Platform:
5051
return isPlatformActive(getPlatformKind(), ctx.LangOpts);
52+
case Kind::Custom:
53+
// For now, custom domains are always active but it's conceivable that in
54+
// the future someone might want to define a domain but leave it inactive.
55+
return true;
5156
}
5257
}
5358

@@ -63,6 +68,8 @@ llvm::StringRef AvailabilityDomain::getNameForDiagnostics() const {
6368
return "Embedded Swift";
6469
case Kind::Platform:
6570
return swift::prettyPlatformString(getPlatformKind());
71+
case Kind::Custom:
72+
return getCustomDomain()->getName().str();
6673
}
6774
}
6875

@@ -78,9 +85,18 @@ llvm::StringRef AvailabilityDomain::getNameForAttributePrinting() const {
7885
return "Embedded";
7986
case Kind::Platform:
8087
return swift::platformString(getPlatformKind());
88+
case Kind::Custom:
89+
return getCustomDomain()->getName().str();
8190
}
8291
}
8392

93+
ModuleDecl *AvailabilityDomain::getModule() const {
94+
if (auto customDomain = getCustomDomain())
95+
return customDomain->getModule();
96+
97+
return nullptr;
98+
}
99+
84100
bool AvailabilityDomain::contains(const AvailabilityDomain &other) const {
85101
// FIXME: [availability] This currently implements something closer to a
86102
// total ordering instead of the more flexible partial ordering that it
@@ -100,5 +116,20 @@ bool AvailabilityDomain::contains(const AvailabilityDomain &other) const {
100116
return true;
101117
return inheritsAvailabilityFromPlatform(other.getPlatformKind(),
102118
getPlatformKind());
119+
case Kind::Custom:
120+
return getCustomDomain() == other.getCustomDomain();
103121
}
104122
}
123+
124+
CustomAvailabilityDomain::CustomAvailabilityDomain(Identifier name,
125+
ModuleDecl *mod, Kind kind)
126+
: name(name), kind(kind), mod(mod) {
127+
ASSERT(!name.empty());
128+
ASSERT(mod);
129+
}
130+
131+
CustomAvailabilityDomain *
132+
CustomAvailabilityDomain::create(const ASTContext &ctx, StringRef name,
133+
ModuleDecl *mod, Kind kind) {
134+
return new (ctx) CustomAvailabilityDomain(ctx.getIdentifier(name), mod, kind);
135+
}

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3006,6 +3006,7 @@ bool shouldHideDomainNameForConstraintDiagnostic(
30063006
switch (constraint.getDomain().getKind()) {
30073007
case AvailabilityDomain::Kind::Universal:
30083008
case AvailabilityDomain::Kind::Embedded:
3009+
case AvailabilityDomain::Kind::Custom:
30093010
return true;
30103011
case AvailabilityDomain::Kind::Platform:
30113012
return false;

0 commit comments

Comments
 (0)