Skip to content

Further adoption of SemanticAvailableAttr #78454

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
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
4ed62e3
AST: Introduce Decl::getAvailableAttrForPlatformIntroduction().
tshortli Jan 3, 2025
f1d0885
AST: Adopt SemanticAvailableAttr in AvailabilityConstraint.
tshortli Jan 6, 2025
efa1aff
AST: Introduce SemanticAvailableAttr::getIntroducedRange().
tshortli Jan 6, 2025
dcfe563
AST: Remove AvailabilityInference::availableRangeAndAttr()
tshortli Jan 6, 2025
f9f8cfb
ModuleInterface: Use SemanticAvailableAttr.
tshortli Jan 6, 2025
3716e97
SymbolGraphGen: Adopt SemanticAvailableAttr.
tshortli Jan 6, 2025
7eb5323
Sema: Adopt SemanticAvailableAttr in deprecation diagnostics.
tshortli Jan 6, 2025
a4203ed
Sema: Adopt SemanticAvailableAttr in override availability checking.
tshortli Jan 6, 2025
51ae094
CodeCompletion: Adopt SemanticAvailableAttr.
tshortli Jan 6, 2025
c76c637
Sema: Adopt SemanticAvailableAttr in ExprAvailabilityWalker.
tshortli Jan 6, 2025
0421835
AST: Adopt SemanticAvailableAttr in availability attribute inference.
tshortli Jan 6, 2025
188ed0e
AST: Adopt SemanticAvailableAttr more completely in AST printing.
tshortli Jan 6, 2025
680bb5b
ConstExtract: Adopt SemanticAvailableAttr more thoroughly.
tshortli Jan 6, 2025
d0b418b
PrintAsClang: Adopt SemanticAvailableAttr more thoroughly.
tshortli Jan 7, 2025
e719d71
Sema: Adopt SemanticAvailableAttr more thoroughly in unavailability d…
tshortli Jan 7, 2025
f58a269
Sema: Adopt SemanticAvailableAttr more thoroughly in TypeCheckConcurr…
tshortli Jan 7, 2025
77141c5
SourceKit: Adopt SemanticAvailableAttr in SwiftDocSupport.cpp.
tshortli Jan 7, 2025
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
10 changes: 9 additions & 1 deletion include/swift/AST/Attr.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "swift/AST/AttrKind.h"
#include "swift/AST/AutoDiff.h"
#include "swift/AST/AvailabilityDomain.h"
#include "swift/AST/AvailabilityRange.h"
#include "swift/AST/ConcreteDeclRef.h"
#include "swift/AST/DeclNameLoc.h"
#include "swift/AST/Identifier.h"
Expand Down Expand Up @@ -3220,7 +3221,7 @@ class ParsedDeclAttributes {
/// informaton, like its corresponding `AvailabilityDomain`.
class SemanticAvailableAttr final {
const AvailableAttr *attr;
const AvailabilityDomain domain;
AvailabilityDomain domain;

public:
SemanticAvailableAttr(const AvailableAttr *attr, AvailabilityDomain domain)
Expand All @@ -3231,14 +3232,21 @@ class SemanticAvailableAttr final {
const AvailableAttr *getParsedAttr() const { return attr; }
const AvailabilityDomain getDomain() const { return domain; }

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

/// Returns the effective range in which the declaration with this attribute
/// was introduced.
AvailabilityRange getIntroducedRange(ASTContext &Ctx) const;

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

/// The version tuple written in source for the `obsoleted:` component.
std::optional<llvm::VersionTuple> getObsoleted() const {
return attr->Obsoleted;
}
Expand Down
14 changes: 7 additions & 7 deletions include/swift/AST/AvailabilityConstraint.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,32 +60,32 @@ class AvailabilityConstraint {

private:
Kind kind;
const AvailableAttr *attr;
SemanticAvailableAttr attr;

AvailabilityConstraint(Kind kind, const AvailableAttr *attr)
AvailabilityConstraint(Kind kind, SemanticAvailableAttr attr)
: kind(kind), attr(attr) {};

public:
static AvailabilityConstraint
forAlwaysUnavailable(const AvailableAttr *attr) {
forAlwaysUnavailable(SemanticAvailableAttr attr) {
return AvailabilityConstraint(Kind::AlwaysUnavailable, attr);
}

static AvailabilityConstraint forObsoleted(const AvailableAttr *attr) {
static AvailabilityConstraint forObsoleted(SemanticAvailableAttr attr) {
return AvailabilityConstraint(Kind::Obsoleted, attr);
}

static AvailabilityConstraint forRequiresVersion(const AvailableAttr *attr) {
static AvailabilityConstraint forRequiresVersion(SemanticAvailableAttr attr) {
return AvailabilityConstraint(Kind::RequiresVersion, attr);
}

static AvailabilityConstraint
forIntroducedInNewerVersion(const AvailableAttr *attr) {
forIntroducedInNewerVersion(SemanticAvailableAttr attr) {
return AvailabilityConstraint(Kind::IntroducedInNewerVersion, attr);
}

Kind getKind() const { return kind; }
const AvailableAttr *getAttr() const { return attr; }
SemanticAvailableAttr getAttr() const { return attr; }

/// Returns the platform that this constraint applies to, or
/// `PlatformKind::none` if it is not platform specific.
Expand Down
17 changes: 0 additions & 17 deletions include/swift/AST/AvailabilityInference.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,26 +46,9 @@ class AvailabilityInference {
/// Returns the range of platform versions in which the decl is available.
static AvailabilityRange availableRange(const Decl *D);

/// Returns the range of platform versions in which the decl is available and
/// the attribute which determined this range (which may be `nullptr` if the
/// declaration is always available.
static std::pair<AvailabilityRange, const AvailableAttr *>
availableRangeAndAttr(const Decl *D);

/// Returns true is the declaration is `@_spi_available`.
static bool isAvailableAsSPI(const Decl *D);

/// Returns the range of platform versions in which a declaration with the
/// given `@available` attribute is available.
///
/// NOTE: The attribute must be active on the current platform.
static AvailabilityRange availableRange(const AvailableAttr *attr,
ASTContext &C);

/// Returns the attribute that should be used to determine the availability
/// range of the given declaration, or nullptr if there is none.
static const AvailableAttr *attrForAnnotatedAvailableRange(const Decl *D);

/// Returns the context for which the declaration
/// is annotated as available, or None if the declaration
/// has no availability annotation.
Expand Down
5 changes: 5 additions & 0 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1430,6 +1430,11 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl>, public Swi
std::optional<SemanticAvailableAttr> getActiveAvailableAttrForCurrentPlatform(
bool ignoreAppExtensions = false) const;

/// Returns the active platform-specific `@available` attribute that should be
/// used to determine the platform introduction version of the decl.
std::optional<SemanticAvailableAttr>
getAvailableAttrForPlatformIntroduction() const;

/// Returns true if the declaration is deprecated at the current deployment
/// target.
bool isDeprecated() const { return getDeprecatedAttr().has_value(); }
Expand Down
57 changes: 28 additions & 29 deletions lib/AST/Attr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -419,27 +419,27 @@ void DeclAttributes::dump(const Decl *D) const {
/// introduction version and does not support deprecation, obsoletion, or
/// messages.
LLVM_READONLY
static bool isShortAvailable(const SemanticAvailableAttr &semanticAttr) {
auto *AvailAttr = semanticAttr.getParsedAttr();
if (AvailAttr->isSPI())
static bool isShortAvailable(const SemanticAvailableAttr &attr) {
auto parsedAttr = attr.getParsedAttr();
if (parsedAttr->isSPI())
return false;

if (!AvailAttr->Introduced.has_value())
if (!attr.getIntroduced().has_value())
return false;

if (AvailAttr->Deprecated.has_value())
if (attr.getDeprecated().has_value())
return false;

if (AvailAttr->Obsoleted.has_value())
if (attr.getObsoleted().has_value())
return false;

if (!AvailAttr->Message.empty())
if (!attr.getMessage().empty())
return false;

if (!AvailAttr->Rename.empty())
if (!attr.getRename().empty())
return false;

switch (AvailAttr->getPlatformAgnosticAvailability()) {
switch (parsedAttr->getPlatformAgnosticAvailability()) {
case PlatformAgnosticAvailabilityKind::Deprecated:
case PlatformAgnosticAvailabilityKind::Unavailable:
case PlatformAgnosticAvailabilityKind::UnavailableInSwift:
Expand Down Expand Up @@ -939,40 +939,39 @@ SemanticAvailableAttributes::Filter::operator()(
return *semanticAttr;
}

static void printAvailableAttr(const Decl *D,
const SemanticAvailableAttr &SemanticAttr,
static void printAvailableAttr(const Decl *D, const SemanticAvailableAttr &Attr,
ASTPrinter &Printer,
const PrintOptions &Options) {
auto Attr = SemanticAttr.getParsedAttr();
auto Domain = SemanticAttr.getDomain();
auto ParsedAttr = Attr.getParsedAttr();
auto Domain = Attr.getDomain();

// The parser rejects `@available(swift, unavailable)`, so when printing
// attributes that are universally unavailable in Swift, we must print them
// as universally unavailable instead.
// FIXME: Reconsider this, it's a weird special case.
if (Domain.isSwiftLanguage() && Attr->isUnconditionallyUnavailable())
if (Domain.isSwiftLanguage() && Attr.isUnconditionallyUnavailable())
Printer << "*";
else
Printer << Domain.getNameForAttributePrinting();

if (Attr->isUnconditionallyUnavailable())
if (Attr.isUnconditionallyUnavailable())
Printer << ", unavailable";
else if (Attr->isUnconditionallyDeprecated())
else if (Attr.isUnconditionallyDeprecated())
Printer << ", deprecated";
else if (Attr->isNoAsync())
else if (Attr.isNoAsync())
Printer << ", noasync";

if (Attr->Introduced)
Printer << ", introduced: " << Attr->Introduced.value().getAsString();
if (Attr->Deprecated)
Printer << ", deprecated: " << Attr->Deprecated.value().getAsString();
if (Attr->Obsoleted)
Printer << ", obsoleted: " << Attr->Obsoleted.value().getAsString();
if (Attr.getIntroduced())
Printer << ", introduced: " << Attr.getIntroduced().value().getAsString();
if (Attr.getDeprecated())
Printer << ", deprecated: " << Attr.getDeprecated().value().getAsString();
if (Attr.getObsoleted())
Printer << ", obsoleted: " << Attr.getObsoleted().value().getAsString();

if (!Attr->Rename.empty()) {
Printer << ", renamed: \"" << Attr->Rename << "\"";
if (!Attr.getRename().empty()) {
Printer << ", renamed: \"" << Attr.getRename() << "\"";
} else if (auto *VD = dyn_cast<ValueDecl>(D)) {
if (auto *renamedDecl = VD->getRenamedDecl(Attr)) {
if (auto *renamedDecl = VD->getRenamedDecl(ParsedAttr)) {
Printer << ", renamed: \"";
if (auto *Accessor = dyn_cast<AccessorDecl>(renamedDecl)) {
SmallString<32> Name;
Expand All @@ -989,10 +988,10 @@ static void printAvailableAttr(const Decl *D,
// If there's no message, but this is specifically an imported
// "unavailable in Swift" attribute, synthesize a message to look good in
// the generated interface.
if (!Attr->Message.empty()) {
if (!Attr.getMessage().empty()) {
Printer << ", message: ";
Printer.printEscapedStringLiteral(Attr->Message);
} else if (Domain.isSwiftLanguage() && Attr->isUnconditionallyUnavailable())
Printer.printEscapedStringLiteral(Attr.getMessage());
} else if (Domain.isSwiftLanguage() && Attr.isUnconditionallyUnavailable())
Printer << ", message: \"Not available in Swift\"";
}

Expand Down
Loading