Skip to content

AST: Eliminate remaining direct access to AvailableAttr's fields #78805

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 1 commit into from
Jan 22, 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
64 changes: 40 additions & 24 deletions include/swift/AST/Attr.h
Original file line number Diff line number Diff line change
Expand Up @@ -719,8 +719,6 @@ enum class AvailableVersionComparison {

/// Defines the @available attribute.
class AvailableAttr : public DeclAttribute {
AvailabilityDomain Domain;

public:
enum class Kind : uint8_t {
/// The attribute does not specify `deprecated`, `unavailable`,
Expand All @@ -744,11 +742,44 @@ class AvailableAttr : public DeclAttribute {
const llvm::VersionTuple &Obsoleted, SourceRange ObsoletedRange,
bool Implicit, bool IsSPI);

/// The optional message.
private:
friend class SemanticAvailableAttr;

AvailabilityDomain Domain;

const StringRef Message;
const StringRef Rename;

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

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

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

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

/// An optional replacement string to emit in a fixit. This allows simple
/// declaration renames to be applied by Xcode.
/// Returns the parsed string for `message:`, which will be presented with
/// diagnostics about the availability of the decl.
StringRef getMessage() const { return Message; }

/// Returns the parsed string for `rename:`, which is an optional replacement
/// string to emit in a fixit. This allows simple declaration renames to be
/// applied by Xcode.
///
/// This should take the form of an operator, identifier, or full function
/// name, optionally with a prefixed type, similar to the syntax used for
Expand All @@ -758,25 +789,7 @@ class AvailableAttr : public DeclAttribute {
/// referred to by this string. Note that this attribute can have a rename
/// target that was provided directly when synthesized and therefore can have
/// a rename decl even when this string is empty.
const StringRef Rename;

/// Indicates when the symbol was introduced.
const std::optional<llvm::VersionTuple> Introduced;

/// Indicates where the Introduced version was specified.
const SourceRange IntroducedRange;

/// Indicates when the symbol was deprecated.
const std::optional<llvm::VersionTuple> Deprecated;

/// Indicates where the Deprecated version was specified.
const SourceRange DeprecatedRange;

/// Indicates when the symbol was obsoleted.
const std::optional<llvm::VersionTuple> Obsoleted;

/// Indicates where the Obsoleted version was specified.
const SourceRange ObsoletedRange;
StringRef getRename() const { return Rename; }

/// Whether this is an unconditionally unavailable entity.
bool isUnconditionallyUnavailable() const;
Expand Down Expand Up @@ -3242,6 +3255,9 @@ class SemanticAvailableAttr final {
return attr->Introduced;
}

/// The source range of the `introduced:` component.
SourceRange getIntroducedSourceRange() const { return attr->IntroducedRange; }

/// Returns the effective range in which the declaration with this attribute
/// was introduced.
AvailabilityRange getIntroducedRange(const ASTContext &Ctx) const;
Expand Down
18 changes: 8 additions & 10 deletions lib/APIDigester/ModuleAnalyzerNodes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1361,11 +1361,10 @@ static bool isABIPlaceholderRecursive(Decl *D) {
StringRef SDKContext::getPlatformIntroVersion(Decl *D, PlatformKind Kind) {
if (!D)
return StringRef();
for (auto semanticAttr : D->getSemanticAvailableAttrs()) {
auto attr = semanticAttr.getParsedAttr();
auto domain = semanticAttr.getDomain();
if (domain.getPlatformKind() == Kind && attr->Introduced) {
return buffer(attr->Introduced->getAsString());
for (auto attr : D->getSemanticAvailableAttrs()) {
auto domain = attr.getDomain();
if (domain.getPlatformKind() == Kind && attr.getIntroduced()) {
return buffer(attr.getIntroduced()->getAsString());
}
}
return StringRef();
Expand All @@ -1374,12 +1373,11 @@ StringRef SDKContext::getPlatformIntroVersion(Decl *D, PlatformKind Kind) {
StringRef SDKContext::getLanguageIntroVersion(Decl *D) {
if (!D)
return StringRef();
for (auto semanticAttr : D->getSemanticAvailableAttrs()) {
auto attr = semanticAttr.getParsedAttr();
auto domain = semanticAttr.getDomain();
for (auto attr : D->getSemanticAvailableAttrs()) {
auto domain = attr.getDomain();

if (domain.isSwiftLanguage() && attr->Introduced) {
return buffer(attr->Introduced->getAsString());
if (domain.isSwiftLanguage() && attr.getIntroduced()) {
return buffer(attr.getIntroduced()->getAsString());
}
}
return getLanguageIntroVersion(D->getDeclContext()->getAsDecl());
Expand Down
29 changes: 13 additions & 16 deletions lib/AST/ASTDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3928,22 +3928,19 @@ class PrintAttribute : public AttributeVisitor<PrintAttribute, void, StringRef>,
printFlag("noasync");
break;
}
if (Attr->Introduced.has_value())
printFieldRaw(
[&](auto &out) { out << Attr->Introduced.value().getAsString(); },
"introduced");
if (Attr->Deprecated.has_value())
printFieldRaw(
[&](auto &out) { out << Attr->Deprecated.value().getAsString(); },
"deprecated");
if (Attr->Obsoleted.has_value())
printFieldRaw(
[&](auto &out) { out << Attr->Obsoleted.value().getAsString(); },
"obsoleted");
if (!Attr->Message.empty())
printFieldQuoted(Attr->Message, "message");
if (!Attr->Rename.empty())
printFieldQuoted(Attr->Rename, "rename");
if (auto introduced = Attr->getRawIntroduced())
printFieldRaw([&](auto &out) { out << introduced.value().getAsString(); },
"introduced");
if (auto deprecated = Attr->getRawDeprecated())
printFieldRaw([&](auto &out) { out << deprecated.value().getAsString(); },
"deprecated");
if (auto obsoleted = Attr->getRawObsoleted())
printFieldRaw([&](auto &out) { out << obsoleted.value().getAsString(); },
"obsoleted");
if (!Attr->getMessage().empty())
printFieldQuoted(Attr->getMessage(), "message");
if (!Attr->getRename().empty())
printFieldQuoted(Attr->getRename(), "rename");
printFoot();
}
void visitBackDeployedAttr(BackDeployedAttr *Attr, StringRef label) {
Expand Down
14 changes: 7 additions & 7 deletions lib/AST/Attr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ isShortFormAvailabilityImpliedByOther(SemanticAvailableAttr Attr,
if (!inheritsAvailabilityFromPlatform(platform, otherPlatform))
continue;

if (Attr.getParsedAttr()->Introduced == other.getParsedAttr()->Introduced)
if (Attr.getIntroduced() == other.getIntroduced())
return true;
}
return false;
Expand All @@ -495,14 +495,14 @@ static void printShortFormAvailable(const Decl *D,

bool isFirst = true;
bool isPlatformAvailability = false;
for (auto semanticAttr : Attrs) {
auto *availAttr = semanticAttr.getParsedAttr();
auto domain = semanticAttr.getDomain();
assert(availAttr->Introduced.has_value());
for (auto attr : Attrs) {
auto domain = attr.getDomain();
auto introduced = attr.getIntroduced();
assert(introduced);

// Avoid omitting available attribute when we are printing module interface.
if (!Options.IsForSwiftInterface &&
isShortFormAvailabilityImpliedByOther(semanticAttr, Attrs))
isShortFormAvailabilityImpliedByOther(attr, Attrs))
continue;

Printer << (isFirst ? "" : ", ");
Expand All @@ -512,7 +512,7 @@ static void printShortFormAvailable(const Decl *D,
isPlatformAvailability = true;

Printer << domain.getNameForAttributePrinting() << " "
<< availAttr->Introduced.value().getAsString();
<< introduced.value().getAsString();
}

if (isPlatformAvailability)
Expand Down
13 changes: 7 additions & 6 deletions lib/AST/Availability.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -557,13 +557,14 @@ std::optional<SemanticAvailableAttr> Decl::getNoAsyncAttr() const {

bool Decl::isUnavailableInCurrentSwiftVersion() const {
llvm::VersionTuple vers = getASTContext().LangOpts.EffectiveLanguageVersion;
for (auto semanticAttr :
getSemanticAvailableAttrs(/*includingInactive=*/false)) {
if (semanticAttr.isSwiftLanguageModeSpecific()) {
auto attr = semanticAttr.getParsedAttr();
if (attr->Introduced.has_value() && attr->Introduced.value() > vers)
for (auto attr : getSemanticAvailableAttrs(/*includingInactive=*/false)) {
if (attr.isSwiftLanguageModeSpecific()) {
auto introduced = attr.getIntroduced();
if (introduced && *introduced > vers)
return true;
if (attr->Obsoleted.has_value() && attr->Obsoleted.value() <= vers)

auto obsoleted = attr.getObsoleted();
if (obsoleted && *obsoleted <= vers)
return true;
}
}
Expand Down
2 changes: 1 addition & 1 deletion lib/AST/AvailabilityScope.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ getAvailabilityConditionVersionSourceRange(const Decl *D, PlatformKind Platform,
if (Range.isValid())
return SourceRange();
else
Range = Attr.getParsedAttr()->IntroducedRange;
Range = Attr.getIntroducedSourceRange();
}
}
return Range;
Expand Down
8 changes: 4 additions & 4 deletions lib/Sema/TypeCheckDeclPrimary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -963,11 +963,11 @@ CheckRedeclarationRequest::evaluate(Evaluator &eval, ValueDecl *current,
public:
static AvailabilityRange from(const ValueDecl *VD) {
AvailabilityRange result;
for (auto semanticAttr : VD->getSemanticAvailableAttrs()) {
if (semanticAttr.isSwiftLanguageModeSpecific()) {
if (auto introduced = semanticAttr.getParsedAttr()->Introduced)
for (auto attr : VD->getSemanticAvailableAttrs()) {
if (attr.isSwiftLanguageModeSpecific()) {
if (auto introduced = attr.getIntroduced())
result.introduced = introduced;
if (auto obsoleted = semanticAttr.getParsedAttr()->Obsoleted)
if (auto obsoleted = attr.getObsoleted())
result.obsoleted = obsoleted;
}
}
Expand Down
32 changes: 17 additions & 15 deletions lib/Serialization/Serialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3060,35 +3060,37 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
}

case DeclAttrKind::Available: {
auto *theAttr = cast<AvailableAttr>(DA);
ENCODE_VER_TUPLE(Introduced, theAttr->Introduced)
ENCODE_VER_TUPLE(Deprecated, theAttr->Deprecated)
ENCODE_VER_TUPLE(Obsoleted, theAttr->Obsoleted)
auto theAttr = D->getSemanticAvailableAttr(cast<AvailableAttr>(DA));
assert(theAttr);

assert(theAttr->Rename.empty() || !theAttr->hasCachedRenamedDecl());
assert(theAttr->hasCachedDomain());
auto domain = theAttr->getCachedDomain();
ENCODE_VER_TUPLE(Introduced, theAttr->getIntroduced())
ENCODE_VER_TUPLE(Deprecated, theAttr->getDeprecated())
ENCODE_VER_TUPLE(Obsoleted, theAttr->getObsoleted())

assert(theAttr->getRename().empty() ||
!theAttr->getParsedAttr()->hasCachedRenamedDecl());
auto domain = theAttr->getDomain();

// FIXME: [availability] Serialize domain and kind directly.
llvm::SmallString<32> blob;
blob.append(theAttr->Message);
blob.append(theAttr->Rename);
blob.append(theAttr->getMessage());
blob.append(theAttr->getRename());
auto abbrCode = S.DeclTypeAbbrCodes[AvailableDeclAttrLayout::Code];
AvailableDeclAttrLayout::emitRecord(
S.Out, S.ScratchRecord, abbrCode,
theAttr->isImplicit(),
theAttr->getParsedAttr()->isImplicit(),
theAttr->isUnconditionallyUnavailable(),
theAttr->isUnconditionallyDeprecated(),
theAttr->isNoAsync(),
domain->isPackageDescription(),
domain.isPackageDescription(),
theAttr->isSPI(),
domain->isEmbedded(),
domain.isEmbedded(),
LIST_VER_TUPLE_PIECES(Introduced),
LIST_VER_TUPLE_PIECES(Deprecated),
LIST_VER_TUPLE_PIECES(Obsoleted),
static_cast<unsigned>(domain->getPlatformKind()),
theAttr->Message.size(),
theAttr->Rename.size(),
static_cast<unsigned>(domain.getPlatformKind()),
theAttr->getMessage().size(),
theAttr->getRename().size(),
blob);
return;
}
Expand Down