Skip to content

Commit 2f34f1d

Browse files
authored
Merge pull request #78829 from tshortli/semantic-available-attr-request
AST: Introduce SemanticAvailableAttrRequest
2 parents 683c02c + dfc741e commit 2f34f1d

File tree

7 files changed

+108
-32
lines changed

7 files changed

+108
-32
lines changed

include/swift/AST/Attr.h

+36-13
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,14 @@ class DeclAttribute : public AttributeBase {
151151
Value : 32
152152
);
153153

154-
SWIFT_INLINE_BITFIELD(AvailableAttr, DeclAttribute, 4+1+1+1,
154+
SWIFT_INLINE_BITFIELD(AvailableAttr, DeclAttribute, 4+1+1+1+1+1,
155155
/// An `AvailableAttr::Kind` value.
156156
Kind : 4,
157157

158+
/// State storage for `SemanticAvailableAttrRequest`.
159+
HasComputedSemanticAttr : 1,
160+
HasDomain : 1,
161+
158162
/// State storage for `RenamedDeclRequest`.
159163
HasComputedRenamedDecl : 1,
160164
HasRenamedDecl : 1,
@@ -750,26 +754,32 @@ class AvailableAttr : public DeclAttribute {
750754
const StringRef Message;
751755
const StringRef Rename;
752756

753-
const std::optional<llvm::VersionTuple> Introduced;
757+
const llvm::VersionTuple Introduced;
754758
const SourceRange IntroducedRange;
755-
const std::optional<llvm::VersionTuple> Deprecated;
759+
const llvm::VersionTuple Deprecated;
756760
const SourceRange DeprecatedRange;
757-
const std::optional<llvm::VersionTuple> Obsoleted;
761+
const llvm::VersionTuple Obsoleted;
758762
const SourceRange ObsoletedRange;
759763

760764
public:
761765
/// Returns the parsed version for `introduced:`.
762766
std::optional<llvm::VersionTuple> getRawIntroduced() const {
767+
if (Introduced.empty())
768+
return std::nullopt;
763769
return Introduced;
764770
}
765771

766772
/// Returns the parsed version for `deprecated:`.
767773
std::optional<llvm::VersionTuple> getRawDeprecated() const {
774+
if (Deprecated.empty())
775+
return std::nullopt;
768776
return Deprecated;
769777
}
770778

771779
/// Returns the parsed version for `obsoleted:`.
772780
std::optional<llvm::VersionTuple> getRawObsoleted() const {
781+
if (Obsoleted.empty())
782+
return std::nullopt;
773783
return Obsoleted;
774784
}
775785

@@ -806,14 +816,15 @@ class AvailableAttr : public DeclAttribute {
806816
/// Returns the `AvailabilityDomain` associated with the attribute, or
807817
/// `std::nullopt` if it has either not yet been resolved or could not be
808818
/// resolved successfully.
809-
std::optional<AvailabilityDomain> getCachedDomain() const { return Domain; }
819+
std::optional<AvailabilityDomain> getCachedDomain() const {
820+
if (hasCachedDomain())
821+
return Domain;
822+
return std::nullopt;
823+
}
810824

811825
/// Returns true if the `AvailabilityDomain` associated with the attribute
812826
/// has been resolved successfully.
813-
bool hasCachedDomain() const {
814-
// For now, domains are always set on construction of the attribute.
815-
return true;
816-
}
827+
bool hasCachedDomain() const { return Bits.AvailableAttr.HasDomain; }
817828

818829
/// Returns the kind of availability the attribute specifies.
819830
Kind getKind() const { return static_cast<Kind>(Bits.AvailableAttr.Kind); }
@@ -873,6 +884,17 @@ class AvailableAttr : public DeclAttribute {
873884
Bits.AvailableAttr.HasComputedRenamedDecl = true;
874885
Bits.AvailableAttr.HasRenamedDecl = hasRenamedDecl;
875886
}
887+
888+
private:
889+
friend class SemanticAvailableAttrRequest;
890+
891+
bool hasComputedSemanticAttr() const {
892+
return Bits.AvailableAttr.HasComputedSemanticAttr;
893+
}
894+
895+
void setComputedSemanticAttr() {
896+
Bits.AvailableAttr.HasComputedSemanticAttr = true;
897+
}
876898
};
877899

878900
/// Indicates that the given declaration is visible to Objective-C.
@@ -3252,7 +3274,7 @@ class SemanticAvailableAttr final {
32523274

32533275
/// The version tuple written in source for the `introduced:` component.
32543276
std::optional<llvm::VersionTuple> getIntroduced() const {
3255-
return attr->Introduced;
3277+
return attr->getRawIntroduced();
32563278
}
32573279

32583280
/// The source range of the `introduced:` component.
@@ -3264,12 +3286,12 @@ class SemanticAvailableAttr final {
32643286

32653287
/// The version tuple written in source for the `deprecated:` component.
32663288
std::optional<llvm::VersionTuple> getDeprecated() const {
3267-
return attr->Deprecated;
3289+
return attr->getRawDeprecated();
32683290
}
32693291

32703292
/// The version tuple written in source for the `obsoleted:` component.
32713293
std::optional<llvm::VersionTuple> getObsoleted() const {
3272-
return attr->Obsoleted;
3294+
return attr->getRawObsoleted();
32733295
}
32743296

32753297
/// Returns the `message:` field of the attribute, or an empty string.
@@ -3302,7 +3324,8 @@ class SemanticAvailableAttr final {
33023324
/// Whether this attribute has an introduced, deprecated, or obsoleted
33033325
/// version.
33043326
bool isVersionSpecific() const {
3305-
return attr->Introduced || attr->Deprecated || attr->Obsoleted;
3327+
return getIntroduced().has_value() || getDeprecated().has_value() ||
3328+
getObsoleted().has_value();
33063329
}
33073330

33083331
/// Whether this is a language mode specific attribute.

include/swift/AST/TypeCheckRequests.h

+21
Original file line numberDiff line numberDiff line change
@@ -5225,6 +5225,27 @@ class CustomDerivativesRequest
52255225
bool isCached() const { return true; }
52265226
};
52275227

5228+
class SemanticAvailableAttrRequest
5229+
: public SimpleRequest<SemanticAvailableAttrRequest,
5230+
std::optional<SemanticAvailableAttr>(
5231+
const AvailableAttr *, const Decl *),
5232+
RequestFlags::SeparatelyCached> {
5233+
public:
5234+
using SimpleRequest::SimpleRequest;
5235+
5236+
private:
5237+
friend SimpleRequest;
5238+
5239+
std::optional<SemanticAvailableAttr> evaluate(Evaluator &evaluator,
5240+
const AvailableAttr *attr,
5241+
const Decl *decl) const;
5242+
5243+
public:
5244+
bool isCached() const { return true; }
5245+
std::optional<std::optional<SemanticAvailableAttr>> getCachedResult() const;
5246+
void cacheResult(std::optional<SemanticAvailableAttr> value) const;
5247+
};
5248+
52285249
#define SWIFT_TYPEID_ZONE TypeChecker
52295250
#define SWIFT_TYPEID_HEADER "swift/AST/TypeCheckerTypeIDZone.def"
52305251
#include "swift/Basic/DefineTypeIDZone.h"

include/swift/AST/TypeCheckerTypeIDZone.def

+5
Original file line numberDiff line numberDiff line change
@@ -614,3 +614,8 @@ SWIFT_REQUEST(TypeChecker, CustomDerivativesRequest,
614614

615615
SWIFT_REQUEST(TypeChecker, GenericTypeParamDeclGetValueTypeRequest,
616616
Type(GenericTypeParamDecl *), Cached, NoLocationInfo)
617+
618+
SWIFT_REQUEST(TypeChecker, SemanticAvailableAttrRequest,
619+
std::optional<SemanticAvailableAttr>
620+
(const AvailableAttr *, const Decl *),
621+
SeparatelyCached, NoLocationInfo)

lib/AST/Attr.cpp

+11-16
Original file line numberDiff line numberDiff line change
@@ -2108,8 +2108,6 @@ Type RawLayoutAttr::getResolvedCountType(StructDecl *sd) const {
21082108
ErrorType::get(ctx));
21092109
}
21102110

2111-
#define INIT_VER_TUPLE(X) X(X.empty() ? std::optional<llvm::VersionTuple>() : X)
2112-
21132111
AvailableAttr::AvailableAttr(
21142112
SourceLoc AtLoc, SourceRange Range, const AvailabilityDomain &Domain,
21152113
Kind Kind, StringRef Message, StringRef Rename,
@@ -2118,18 +2116,18 @@ AvailableAttr::AvailableAttr(
21182116
const llvm::VersionTuple &Obsoleted, SourceRange ObsoletedRange,
21192117
bool Implicit, bool IsSPI)
21202118
: DeclAttribute(DeclAttrKind::Available, AtLoc, Range, Implicit),
2121-
Domain(Domain), Message(Message), Rename(Rename),
2122-
INIT_VER_TUPLE(Introduced), IntroducedRange(IntroducedRange),
2123-
INIT_VER_TUPLE(Deprecated), DeprecatedRange(DeprecatedRange),
2124-
INIT_VER_TUPLE(Obsoleted), ObsoletedRange(ObsoletedRange) {
2119+
Domain(Domain), Message(Message), Rename(Rename), Introduced(Introduced),
2120+
IntroducedRange(IntroducedRange), Deprecated(Deprecated),
2121+
DeprecatedRange(DeprecatedRange), Obsoleted(Obsoleted),
2122+
ObsoletedRange(ObsoletedRange) {
21252123
Bits.AvailableAttr.Kind = static_cast<uint8_t>(Kind);
2124+
Bits.AvailableAttr.HasComputedSemanticAttr = false;
2125+
Bits.AvailableAttr.HasDomain = true;
21262126
Bits.AvailableAttr.HasComputedRenamedDecl = false;
21272127
Bits.AvailableAttr.HasRenamedDecl = false;
21282128
Bits.AvailableAttr.IsSPI = IsSPI;
21292129
}
21302130

2131-
#undef INIT_VER_TUPLE
2132-
21332131
AvailableAttr *AvailableAttr::createUniversallyUnavailable(ASTContext &C,
21342132
StringRef Message,
21352133
StringRef Rename) {
@@ -2197,12 +2195,9 @@ bool BackDeployedAttr::isActivePlatform(const ASTContext &ctx,
21972195
AvailableAttr *AvailableAttr::clone(ASTContext &C, bool implicit) const {
21982196
return new (C) AvailableAttr(
21992197
implicit ? SourceLoc() : AtLoc, implicit ? SourceRange() : getRange(),
2200-
Domain, getKind(), Message, Rename,
2201-
Introduced ? *Introduced : llvm::VersionTuple(),
2202-
implicit ? SourceRange() : IntroducedRange,
2203-
Deprecated ? *Deprecated : llvm::VersionTuple(),
2204-
implicit ? SourceRange() : DeprecatedRange,
2205-
Obsoleted ? *Obsoleted : llvm::VersionTuple(),
2198+
Domain, getKind(), Message, Rename, Introduced,
2199+
implicit ? SourceRange() : IntroducedRange, Deprecated,
2200+
implicit ? SourceRange() : DeprecatedRange, Obsoleted,
22062201
implicit ? SourceRange() : ObsoletedRange, implicit, isSPI());
22072202
}
22082203

@@ -2292,7 +2287,7 @@ SemanticAvailableAttr::getVersionAvailability(const ASTContext &ctx) const {
22922287
return AvailableVersionComparison::Unavailable;
22932288

22942289
llvm::VersionTuple queryVersion = getActiveVersion(ctx);
2295-
std::optional<llvm::VersionTuple> ObsoletedVersion = attr->Obsoleted;
2290+
std::optional<llvm::VersionTuple> ObsoletedVersion = getObsoleted();
22962291

22972292
StringRef ObsoletedPlatform;
22982293
llvm::VersionTuple RemappedObsoletedVersion;
@@ -2305,7 +2300,7 @@ SemanticAvailableAttr::getVersionAvailability(const ASTContext &ctx) const {
23052300
if (ObsoletedVersion && *ObsoletedVersion <= queryVersion)
23062301
return AvailableVersionComparison::Obsoleted;
23072302

2308-
std::optional<llvm::VersionTuple> IntroducedVersion = attr->Introduced;
2303+
std::optional<llvm::VersionTuple> IntroducedVersion = getIntroduced();
23092304
StringRef IntroducedPlatform;
23102305
llvm::VersionTuple RemappedIntroducedVersion;
23112306
if (AvailabilityInference::updateIntroducedPlatformForFallback(

lib/AST/Availability.cpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,9 @@ Decl::getSemanticAvailableAttrs(bool includeInactive) const {
447447

448448
std::optional<SemanticAvailableAttr>
449449
Decl::getSemanticAvailableAttr(const AvailableAttr *attr) const {
450-
return SemanticAvailableAttr(attr);
450+
return evaluateOrDefault(getASTContext().evaluator,
451+
SemanticAvailableAttrRequest{attr, this},
452+
std::nullopt);
451453
}
452454

453455
std::optional<SemanticAvailableAttr>
@@ -792,10 +794,10 @@ SemanticAvailableAttr::getIntroducedRange(const ASTContext &Ctx) const {
792794
assert(getDomain().isActive(Ctx));
793795

794796
auto *attr = getParsedAttr();
795-
if (!attr->Introduced.has_value())
797+
if (!attr->getRawIntroduced().has_value())
796798
return AvailabilityRange::alwaysAvailable();
797799

798-
llvm::VersionTuple IntroducedVersion = attr->Introduced.value();
800+
llvm::VersionTuple IntroducedVersion = attr->getRawIntroduced().value();
799801
StringRef Platform;
800802
llvm::VersionTuple RemappedIntroducedVersion;
801803
if (AvailabilityInference::updateIntroducedPlatformForFallback(

lib/AST/TypeCheckRequests.cpp

+23
Original file line numberDiff line numberDiff line change
@@ -2730,3 +2730,26 @@ void IsUnsafeRequest::cacheResult(bool value) const {
27302730
auto *decl = std::get<0>(getStorage());
27312731
decl->setUnsafe(value);
27322732
}
2733+
2734+
//----------------------------------------------------------------------------//
2735+
// SemanticAvailableAttrRequest computation.
2736+
//----------------------------------------------------------------------------//
2737+
2738+
std::optional<std::optional<SemanticAvailableAttr>>
2739+
SemanticAvailableAttrRequest::getCachedResult() const {
2740+
const AvailableAttr *attr = std::get<0>(getStorage());
2741+
if (!attr->hasComputedSemanticAttr())
2742+
return std::nullopt;
2743+
2744+
if (!attr->hasCachedDomain()) {
2745+
return std::optional<SemanticAvailableAttr>{};
2746+
}
2747+
2748+
return SemanticAvailableAttr(attr);
2749+
}
2750+
2751+
void SemanticAvailableAttrRequest::cacheResult(
2752+
std::optional<SemanticAvailableAttr> value) const {
2753+
AvailableAttr *attr = const_cast<AvailableAttr *>(std::get<0>(getStorage()));
2754+
attr->setComputedSemanticAttr();
2755+
}

lib/Sema/TypeCheckAttr.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -8252,6 +8252,13 @@ ValueDecl *RenamedDeclRequest::evaluate(Evaluator &evaluator,
82528252
return renamedDecl;
82538253
}
82548254

8255+
std::optional<SemanticAvailableAttr>
8256+
SemanticAvailableAttrRequest::evaluate(swift::Evaluator &evaluator,
8257+
const AvailableAttr *attr,
8258+
const Decl *decl) const {
8259+
return SemanticAvailableAttr(attr);
8260+
}
8261+
82558262
template <typename ATTR>
82568263
static void forEachCustomAttribute(
82578264
Decl *decl,

0 commit comments

Comments
 (0)