Skip to content

Commit 393ad98

Browse files
authored
Merge pull request #78541 from tshortli/available-attr-remodel
AST: Refactor `AvailableAttr` representation to use `AvailabilityDomain`
2 parents ede7bfe + c0e01dc commit 393ad98

File tree

12 files changed

+291
-278
lines changed

12 files changed

+291
-278
lines changed

include/swift/AST/Attr.h

Lines changed: 28 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -151,12 +151,9 @@ class DeclAttribute : public AttributeBase {
151151
Value : 32
152152
);
153153

154-
SWIFT_INLINE_BITFIELD(AvailableAttr, DeclAttribute, 8+8+1+1+1+1,
155-
/// A `PlatformKind` value.
156-
Platform : 8,
157-
158-
/// A `PlatformAgnosticAvailabilityKind` value.
159-
PlatformAgnostic : 8,
154+
SWIFT_INLINE_BITFIELD(AvailableAttr, DeclAttribute, 4+1+1+1+1,
155+
/// An `AvailableAttr::Kind` value.
156+
Kind : 4,
160157

161158
/// State storage for `RenamedDeclRequest`.
162159
HasComputedRenamedDecl : 1,
@@ -719,38 +716,31 @@ enum class AvailableVersionComparison {
719716
Obsoleted,
720717
};
721718

722-
/// Describes the platform-agnostic availability of a declaration.
723-
enum class PlatformAgnosticAvailabilityKind : uint8_t {
724-
/// The associated availability attribute is not platform-agnostic.
725-
None,
726-
/// The declaration is deprecated, but can still be used.
727-
Deprecated,
728-
/// The declaration is unavailable in Swift, specifically
729-
UnavailableInSwift,
730-
/// The declaration is available in some but not all versions
731-
/// of Swift, as specified by the VersionTuple members.
732-
SwiftVersionSpecific,
733-
/// The declaration is available in some but not all versions
734-
/// of SwiftPM's PackageDescription library, as specified by
735-
/// the VersionTuple members.
736-
PackageDescriptionVersionSpecific,
737-
/// The declaration is unavailable for other reasons.
738-
Unavailable,
739-
/// The declaration is unavailable from asynchronous contexts
740-
NoAsync,
741-
};
742-
743719
/// Defines the @available attribute.
744720
class AvailableAttr : public DeclAttribute {
745-
public:
746-
AvailableAttr(SourceLoc AtLoc, SourceRange Range, PlatformKind Platform,
747-
StringRef Message, StringRef Rename,
748-
const llvm::VersionTuple &Introduced,
721+
AvailabilityDomain Domain;
722+
723+
public:
724+
enum class Kind : uint8_t {
725+
/// The attribute does not specify `deprecated`, `unavailable`,
726+
/// or `noasync`. Instead, it may specify `introduced:`, `deprecated:`, or
727+
/// `obsoleted:` versions or it may simply have a `rename:` field.
728+
Default,
729+
/// The attribute specifies unconditional deprecation.
730+
Deprecated,
731+
/// The attribute specifies unconditional unavailability.
732+
Unavailable,
733+
/// The attribute specifies unavailability in asynchronous contexts.
734+
NoAsync,
735+
};
736+
737+
AvailableAttr(SourceLoc AtLoc, SourceRange Range,
738+
const AvailabilityDomain &Domain, Kind Kind, StringRef Message,
739+
StringRef Rename, const llvm::VersionTuple &Introduced,
749740
SourceRange IntroducedRange,
750741
const llvm::VersionTuple &Deprecated,
751742
SourceRange DeprecatedRange,
752743
const llvm::VersionTuple &Obsoleted, SourceRange ObsoletedRange,
753-
PlatformAgnosticAvailabilityKind PlatformAgnostic,
754744
bool Implicit, bool IsSPI, bool IsForEmbedded = false);
755745

756746
/// The optional message.
@@ -802,16 +792,13 @@ class AvailableAttr : public DeclAttribute {
802792
/// Whether this attribute was spelled `@_unavailableInEmbedded`.
803793
bool isForEmbedded() const { return Bits.AvailableAttr.IsForEmbedded; }
804794

805-
/// Returns the platform that the attribute applies to (may be `none`).
806-
PlatformKind getPlatform() const {
807-
return static_cast<PlatformKind>(Bits.AvailableAttr.Platform);
808-
}
795+
/// Returns the `AvailabilityDomain` associated with the attribute, or
796+
/// `std::nullopt` if it has either not yet been resolved or could not be
797+
/// resolved successfully.
798+
std::optional<AvailabilityDomain> getCachedDomain() const { return Domain; }
809799

810-
/// Returns the platform-agnostic availability.
811-
PlatformAgnosticAvailabilityKind getPlatformAgnosticAvailability() const {
812-
return static_cast<PlatformAgnosticAvailabilityKind>(
813-
Bits.AvailableAttr.PlatformAgnostic);
814-
}
800+
/// Returns the kind of availability the attribute specifies.
801+
Kind getKind() const { return static_cast<Kind>(Bits.AvailableAttr.Kind); }
815802

816803
/// Create an `AvailableAttr` that specifies universal unavailability, e.g.
817804
/// `@available(*, unavailable)`.

include/swift/AST/AvailabilityDomain.h

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,14 @@ class AvailabilityDomain final {
3333
/// universally unavailable or deprecated, for example.
3434
Universal,
3535

36-
/// Represents availability for a specific operating system platform.
37-
Platform,
38-
3936
/// Represents availability with respect to Swift language mode.
4037
SwiftLanguage,
4138

4239
/// Represents PackageDescription availability.
4340
PackageDescription,
41+
42+
/// Represents availability for a specific operating system platform.
43+
Platform,
4444
};
4545

4646
private:
@@ -57,6 +57,8 @@ class AvailabilityDomain final {
5757
};
5858

5959
public:
60+
AvailabilityDomain() {}
61+
6062
static AvailabilityDomain forUniversal() {
6163
return AvailabilityDomain(Kind::Universal);
6264
}
@@ -96,6 +98,40 @@ class AvailabilityDomain final {
9698

9799
/// Returns the string to use when printing an `@available` attribute.
98100
llvm::StringRef getNameForAttributePrinting() const;
101+
102+
bool operator==(const AvailabilityDomain &other) const {
103+
if (getKind() != other.getKind())
104+
return false;
105+
106+
switch (getKind()) {
107+
case Kind::Universal:
108+
case Kind::SwiftLanguage:
109+
case Kind::PackageDescription:
110+
// These availability domains are singletons.
111+
return true;
112+
case Kind::Platform:
113+
return getPlatformKind() == other.getPlatformKind();
114+
}
115+
}
116+
117+
bool operator!=(const AvailabilityDomain &other) const {
118+
return !(*this == other);
119+
}
120+
121+
bool operator<(const AvailabilityDomain &other) const {
122+
if (getKind() != other.getKind())
123+
return getKind() < other.getKind();
124+
125+
switch (getKind()) {
126+
case Kind::Universal:
127+
case Kind::SwiftLanguage:
128+
case Kind::PackageDescription:
129+
// These availability domains are singletons.
130+
return false;
131+
case Kind::Platform:
132+
return getPlatformKind() < other.getPlatformKind();
133+
}
134+
}
99135
};
100136

101137
} // end namespace swift

lib/AST/ASTDumper.cpp

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3897,11 +3897,23 @@ class PrintAttribute : public AttributeVisitor<PrintAttribute, void, StringRef>,
38973897
}
38983898
void visitAvailableAttr(AvailableAttr *Attr, StringRef label) {
38993899
printCommon(Attr, "available_attr", label);
3900-
printField(Attr->getPlatform(), "platform");
3901-
if (!Attr->Message.empty())
3902-
printFieldQuoted(Attr->Message, "message");
3903-
if (!Attr->Rename.empty())
3904-
printFieldQuoted(Attr->Rename, "rename");
3900+
3901+
if (auto domain = Attr->getCachedDomain())
3902+
printField(domain->getNameForAttributePrinting(), "platform");
3903+
3904+
switch (Attr->getKind()) {
3905+
case swift::AvailableAttr::Kind::Default:
3906+
break;
3907+
case swift::AvailableAttr::Kind::Deprecated:
3908+
printFlag("deprecated");
3909+
break;
3910+
case swift::AvailableAttr::Kind::Unavailable:
3911+
printFlag("unavailable");
3912+
break;
3913+
case swift::AvailableAttr::Kind::NoAsync:
3914+
printFlag("noasync");
3915+
break;
3916+
}
39053917
if (Attr->Introduced.has_value())
39063918
printFieldRaw(
39073919
[&](auto &out) { out << Attr->Introduced.value().getAsString(); },
@@ -3914,6 +3926,10 @@ class PrintAttribute : public AttributeVisitor<PrintAttribute, void, StringRef>,
39143926
printFieldRaw(
39153927
[&](auto &out) { out << Attr->Obsoleted.value().getAsString(); },
39163928
"obsoleted");
3929+
if (!Attr->Message.empty())
3930+
printFieldQuoted(Attr->Message, "message");
3931+
if (!Attr->Rename.empty())
3932+
printFieldQuoted(Attr->Rename, "rename");
39173933
printFoot();
39183934
}
39193935
void visitBackDeployedAttr(BackDeployedAttr *Attr, StringRef label) {

0 commit comments

Comments
 (0)