Skip to content

AST: Introduce SemanticAvailableAttrRequest #78829

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 2 commits into from
Jan 23, 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
49 changes: 36 additions & 13 deletions include/swift/AST/Attr.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,14 @@ class DeclAttribute : public AttributeBase {
Value : 32
);

SWIFT_INLINE_BITFIELD(AvailableAttr, DeclAttribute, 4+1+1+1,
SWIFT_INLINE_BITFIELD(AvailableAttr, DeclAttribute, 4+1+1+1+1+1,
/// An `AvailableAttr::Kind` value.
Kind : 4,

/// State storage for `SemanticAvailableAttrRequest`.
HasComputedSemanticAttr : 1,
HasDomain : 1,

/// State storage for `RenamedDeclRequest`.
HasComputedRenamedDecl : 1,
HasRenamedDecl : 1,
Expand Down Expand Up @@ -750,26 +754,32 @@ class AvailableAttr : public DeclAttribute {
const StringRef Message;
const StringRef Rename;

const std::optional<llvm::VersionTuple> Introduced;
const llvm::VersionTuple Introduced;
const SourceRange IntroducedRange;
const std::optional<llvm::VersionTuple> Deprecated;
const llvm::VersionTuple Deprecated;
const SourceRange DeprecatedRange;
const std::optional<llvm::VersionTuple> Obsoleted;
const llvm::VersionTuple Obsoleted;
const SourceRange ObsoletedRange;

public:
/// Returns the parsed version for `introduced:`.
std::optional<llvm::VersionTuple> getRawIntroduced() const {
if (Introduced.empty())
return std::nullopt;
return Introduced;
}

/// Returns the parsed version for `deprecated:`.
std::optional<llvm::VersionTuple> getRawDeprecated() const {
if (Deprecated.empty())
return std::nullopt;
return Deprecated;
}

/// Returns the parsed version for `obsoleted:`.
std::optional<llvm::VersionTuple> getRawObsoleted() const {
if (Obsoleted.empty())
return std::nullopt;
return Obsoleted;
}

Expand Down Expand Up @@ -806,14 +816,15 @@ class AvailableAttr : public DeclAttribute {
/// Returns the `AvailabilityDomain` associated with the attribute, or
/// `std::nullopt` if it has either not yet been resolved or could not be
/// resolved successfully.
std::optional<AvailabilityDomain> getCachedDomain() const { return Domain; }
std::optional<AvailabilityDomain> getCachedDomain() const {
if (hasCachedDomain())
return Domain;
return std::nullopt;
}

/// Returns true if the `AvailabilityDomain` associated with the attribute
/// has been resolved successfully.
bool hasCachedDomain() const {
// For now, domains are always set on construction of the attribute.
return true;
}
bool hasCachedDomain() const { return Bits.AvailableAttr.HasDomain; }

/// Returns the kind of availability the attribute specifies.
Kind getKind() const { return static_cast<Kind>(Bits.AvailableAttr.Kind); }
Expand Down Expand Up @@ -873,6 +884,17 @@ class AvailableAttr : public DeclAttribute {
Bits.AvailableAttr.HasComputedRenamedDecl = true;
Bits.AvailableAttr.HasRenamedDecl = hasRenamedDecl;
}

private:
friend class SemanticAvailableAttrRequest;

bool hasComputedSemanticAttr() const {
return Bits.AvailableAttr.HasComputedSemanticAttr;
}

void setComputedSemanticAttr() {
Bits.AvailableAttr.HasComputedSemanticAttr = true;
}
};

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

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

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

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

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

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

/// Whether this is a language mode specific attribute.
Expand Down
21 changes: 21 additions & 0 deletions include/swift/AST/TypeCheckRequests.h
Original file line number Diff line number Diff line change
Expand Up @@ -5225,6 +5225,27 @@ class CustomDerivativesRequest
bool isCached() const { return true; }
};

class SemanticAvailableAttrRequest
: public SimpleRequest<SemanticAvailableAttrRequest,
std::optional<SemanticAvailableAttr>(
const AvailableAttr *, const Decl *),
RequestFlags::SeparatelyCached> {
public:
using SimpleRequest::SimpleRequest;

private:
friend SimpleRequest;

std::optional<SemanticAvailableAttr> evaluate(Evaluator &evaluator,
const AvailableAttr *attr,
const Decl *decl) const;

public:
bool isCached() const { return true; }
std::optional<std::optional<SemanticAvailableAttr>> getCachedResult() const;
void cacheResult(std::optional<SemanticAvailableAttr> value) const;
};

#define SWIFT_TYPEID_ZONE TypeChecker
#define SWIFT_TYPEID_HEADER "swift/AST/TypeCheckerTypeIDZone.def"
#include "swift/Basic/DefineTypeIDZone.h"
Expand Down
5 changes: 5 additions & 0 deletions include/swift/AST/TypeCheckerTypeIDZone.def
Original file line number Diff line number Diff line change
Expand Up @@ -614,3 +614,8 @@ SWIFT_REQUEST(TypeChecker, CustomDerivativesRequest,

SWIFT_REQUEST(TypeChecker, GenericTypeParamDeclGetValueTypeRequest,
Type(GenericTypeParamDecl *), Cached, NoLocationInfo)

SWIFT_REQUEST(TypeChecker, SemanticAvailableAttrRequest,
std::optional<SemanticAvailableAttr>
(const AvailableAttr *, const Decl *),
SeparatelyCached, NoLocationInfo)
27 changes: 11 additions & 16 deletions lib/AST/Attr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2108,8 +2108,6 @@ Type RawLayoutAttr::getResolvedCountType(StructDecl *sd) const {
ErrorType::get(ctx));
}

#define INIT_VER_TUPLE(X) X(X.empty() ? std::optional<llvm::VersionTuple>() : X)

AvailableAttr::AvailableAttr(
SourceLoc AtLoc, SourceRange Range, const AvailabilityDomain &Domain,
Kind Kind, StringRef Message, StringRef Rename,
Expand All @@ -2118,18 +2116,18 @@ AvailableAttr::AvailableAttr(
const llvm::VersionTuple &Obsoleted, SourceRange ObsoletedRange,
bool Implicit, bool IsSPI)
: DeclAttribute(DeclAttrKind::Available, AtLoc, Range, Implicit),
Domain(Domain), Message(Message), Rename(Rename),
INIT_VER_TUPLE(Introduced), IntroducedRange(IntroducedRange),
INIT_VER_TUPLE(Deprecated), DeprecatedRange(DeprecatedRange),
INIT_VER_TUPLE(Obsoleted), ObsoletedRange(ObsoletedRange) {
Domain(Domain), Message(Message), Rename(Rename), Introduced(Introduced),
IntroducedRange(IntroducedRange), Deprecated(Deprecated),
DeprecatedRange(DeprecatedRange), Obsoleted(Obsoleted),
ObsoletedRange(ObsoletedRange) {
Bits.AvailableAttr.Kind = static_cast<uint8_t>(Kind);
Bits.AvailableAttr.HasComputedSemanticAttr = false;
Bits.AvailableAttr.HasDomain = true;
Bits.AvailableAttr.HasComputedRenamedDecl = false;
Bits.AvailableAttr.HasRenamedDecl = false;
Bits.AvailableAttr.IsSPI = IsSPI;
}

#undef INIT_VER_TUPLE

AvailableAttr *AvailableAttr::createUniversallyUnavailable(ASTContext &C,
StringRef Message,
StringRef Rename) {
Expand Down Expand Up @@ -2197,12 +2195,9 @@ bool BackDeployedAttr::isActivePlatform(const ASTContext &ctx,
AvailableAttr *AvailableAttr::clone(ASTContext &C, bool implicit) const {
return new (C) AvailableAttr(
implicit ? SourceLoc() : AtLoc, implicit ? SourceRange() : getRange(),
Domain, getKind(), Message, Rename,
Introduced ? *Introduced : llvm::VersionTuple(),
implicit ? SourceRange() : IntroducedRange,
Deprecated ? *Deprecated : llvm::VersionTuple(),
implicit ? SourceRange() : DeprecatedRange,
Obsoleted ? *Obsoleted : llvm::VersionTuple(),
Domain, getKind(), Message, Rename, Introduced,
implicit ? SourceRange() : IntroducedRange, Deprecated,
implicit ? SourceRange() : DeprecatedRange, Obsoleted,
implicit ? SourceRange() : ObsoletedRange, implicit, isSPI());
}

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

llvm::VersionTuple queryVersion = getActiveVersion(ctx);
std::optional<llvm::VersionTuple> ObsoletedVersion = attr->Obsoleted;
std::optional<llvm::VersionTuple> ObsoletedVersion = getObsoleted();

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

std::optional<llvm::VersionTuple> IntroducedVersion = attr->Introduced;
std::optional<llvm::VersionTuple> IntroducedVersion = getIntroduced();
StringRef IntroducedPlatform;
llvm::VersionTuple RemappedIntroducedVersion;
if (AvailabilityInference::updateIntroducedPlatformForFallback(
Expand Down
8 changes: 5 additions & 3 deletions lib/AST/Availability.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,9 @@ Decl::getSemanticAvailableAttrs(bool includeInactive) const {

std::optional<SemanticAvailableAttr>
Decl::getSemanticAvailableAttr(const AvailableAttr *attr) const {
return SemanticAvailableAttr(attr);
return evaluateOrDefault(getASTContext().evaluator,
SemanticAvailableAttrRequest{attr, this},
std::nullopt);
}

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

auto *attr = getParsedAttr();
if (!attr->Introduced.has_value())
if (!attr->getRawIntroduced().has_value())
return AvailabilityRange::alwaysAvailable();

llvm::VersionTuple IntroducedVersion = attr->Introduced.value();
llvm::VersionTuple IntroducedVersion = attr->getRawIntroduced().value();
StringRef Platform;
llvm::VersionTuple RemappedIntroducedVersion;
if (AvailabilityInference::updateIntroducedPlatformForFallback(
Expand Down
23 changes: 23 additions & 0 deletions lib/AST/TypeCheckRequests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2730,3 +2730,26 @@ void IsUnsafeRequest::cacheResult(bool value) const {
auto *decl = std::get<0>(getStorage());
decl->setUnsafe(value);
}

//----------------------------------------------------------------------------//
// SemanticAvailableAttrRequest computation.
//----------------------------------------------------------------------------//

std::optional<std::optional<SemanticAvailableAttr>>
SemanticAvailableAttrRequest::getCachedResult() const {
const AvailableAttr *attr = std::get<0>(getStorage());
if (!attr->hasComputedSemanticAttr())
return std::nullopt;

if (!attr->hasCachedDomain()) {
return std::optional<SemanticAvailableAttr>{};
}

return SemanticAvailableAttr(attr);
}

void SemanticAvailableAttrRequest::cacheResult(
std::optional<SemanticAvailableAttr> value) const {
AvailableAttr *attr = const_cast<AvailableAttr *>(std::get<0>(getStorage()));
attr->setComputedSemanticAttr();
}
7 changes: 7 additions & 0 deletions lib/Sema/TypeCheckAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8252,6 +8252,13 @@ ValueDecl *RenamedDeclRequest::evaluate(Evaluator &evaluator,
return renamedDecl;
}

std::optional<SemanticAvailableAttr>
SemanticAvailableAttrRequest::evaluate(swift::Evaluator &evaluator,
const AvailableAttr *attr,
const Decl *decl) const {
return SemanticAvailableAttr(attr);
}

template <typename ATTR>
static void forEachCustomAttribute(
Decl *decl,
Expand Down