Skip to content

Commit 3db2b97

Browse files
authored
Merge pull request #79520 from tshortli/sink-semantic-available-attr-request
AST/Sema: Sink `SemanticAvailableAttrRequest` from Sema into AST
2 parents b44367e + f4f9d85 commit 3db2b97

File tree

2 files changed

+140
-137
lines changed

2 files changed

+140
-137
lines changed

lib/AST/Availability.cpp

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
#include "swift/AST/AvailabilityInference.h"
2323
#include "swift/AST/AvailabilityRange.h"
2424
#include "swift/AST/Decl.h"
25+
// FIXME: [availability] Remove this when possible
26+
#include "swift/AST/DiagnosticsParse.h"
27+
#include "swift/AST/DiagnosticsSema.h"
2528
#include "swift/AST/PlatformKind.h"
2629
#include "swift/AST/TypeCheckRequests.h"
2730
#include "swift/AST/TypeWalker.h"
@@ -794,6 +797,143 @@ bool AvailabilityInference::isAvailableAsSPI(const Decl *D) {
794797
return false;
795798
}
796799

800+
static std::optional<AvailabilityDomain>
801+
getAvailabilityDomainForName(Identifier identifier,
802+
const DeclContext *declContext) {
803+
if (auto builtinDomain = AvailabilityDomain::builtinDomainForString(
804+
identifier.str(), declContext))
805+
return builtinDomain;
806+
807+
auto &ctx = declContext->getASTContext();
808+
if (auto customDomain =
809+
ctx.MainModule->getAvailabilityDomainForIdentifier(identifier))
810+
return customDomain;
811+
812+
return std::nullopt;
813+
}
814+
815+
std::optional<SemanticAvailableAttr>
816+
SemanticAvailableAttrRequest::evaluate(swift::Evaluator &evaluator,
817+
const AvailableAttr *attr,
818+
const Decl *decl) const {
819+
if (attr->hasCachedDomain())
820+
return SemanticAvailableAttr(attr);
821+
822+
auto &ctx = decl->getASTContext();
823+
auto &diags = ctx.Diags;
824+
auto attrLoc = attr->getLocation();
825+
auto attrName = attr->getAttrName();
826+
auto domainLoc = attr->getDomainLoc();
827+
auto introducedVersion = attr->getRawIntroduced();
828+
auto deprecatedVersion = attr->getRawDeprecated();
829+
auto obsoletedVersion = attr->getRawObsoleted();
830+
auto mutableAttr = const_cast<AvailableAttr *>(attr);
831+
auto domain = attr->getCachedDomain();
832+
833+
if (!domain) {
834+
auto domainIdentifier = attr->getDomainIdentifier();
835+
ASSERT(domainIdentifier);
836+
837+
// Attempt to resolve the domain specified for the attribute and diagnose
838+
// if no domain is found.
839+
auto declContext = decl->getInnermostDeclContext();
840+
domain = getAvailabilityDomainForName(*domainIdentifier, declContext);
841+
if (!domain) {
842+
auto domainString = domainIdentifier->str();
843+
if (auto suggestion = closestCorrectedPlatformString(domainString)) {
844+
diags
845+
.diagnose(domainLoc, diag::attr_availability_suggest_platform,
846+
domainString, attrName, *suggestion)
847+
.fixItReplace(SourceRange(domainLoc), *suggestion);
848+
} else {
849+
diags.diagnose(attrLoc, diag::attr_availability_unknown_platform,
850+
domainString, attrName);
851+
}
852+
return std::nullopt;
853+
}
854+
855+
if (domain->isCustom() &&
856+
!ctx.LangOpts.hasFeature(Feature::CustomAvailability) &&
857+
!declContext->isInSwiftinterface()) {
858+
diags.diagnose(domainLoc,
859+
diag::attr_availability_requires_custom_availability,
860+
domain->getNameForAttributePrinting(), attr);
861+
return std::nullopt;
862+
}
863+
864+
mutableAttr->setCachedDomain(*domain);
865+
}
866+
867+
auto domainName = domain->getNameForAttributePrinting();
868+
auto semanticAttr = SemanticAvailableAttr(attr);
869+
870+
bool hasVersionSpec =
871+
(introducedVersion || deprecatedVersion || obsoletedVersion);
872+
873+
if (!domain->isVersioned() && hasVersionSpec) {
874+
SourceRange versionSourceRange;
875+
if (introducedVersion)
876+
versionSourceRange = semanticAttr.getIntroducedSourceRange();
877+
else if (deprecatedVersion)
878+
versionSourceRange = semanticAttr.getDeprecatedSourceRange();
879+
else if (obsoletedVersion)
880+
versionSourceRange = semanticAttr.getObsoletedSourceRange();
881+
882+
diags
883+
.diagnose(attrLoc, diag::attr_availability_unexpected_version, attr,
884+
domainName)
885+
.highlight(versionSourceRange);
886+
return std::nullopt;
887+
}
888+
889+
if (domain->isSwiftLanguage() || domain->isPackageDescription()) {
890+
switch (attr->getKind()) {
891+
case AvailableAttr::Kind::Deprecated:
892+
diags.diagnose(attrLoc,
893+
diag::attr_availability_expected_deprecated_version,
894+
attrName, domainName);
895+
return std::nullopt;
896+
897+
case AvailableAttr::Kind::Unavailable:
898+
diags.diagnose(attrLoc, diag::attr_availability_cannot_be_used_for_domain,
899+
"unavailable", attrName, domainName);
900+
return std::nullopt;
901+
902+
case AvailableAttr::Kind::NoAsync:
903+
diags.diagnose(attrLoc, diag::attr_availability_cannot_be_used_for_domain,
904+
"noasync", attrName, domainName);
905+
return std::nullopt;
906+
907+
case AvailableAttr::Kind::Default:
908+
break;
909+
}
910+
911+
if (!hasVersionSpec) {
912+
diags.diagnose(attrLoc, diag::attr_availability_expected_version_spec,
913+
attrName, domainName);
914+
return std::nullopt;
915+
}
916+
}
917+
918+
// Canonicalize platform versions.
919+
// FIXME: [availability] This should be done when remapping versions instead.
920+
if (domain->isPlatform()) {
921+
auto canonicalizeVersion = [&](llvm::VersionTuple version) {
922+
return canonicalizePlatformVersion(domain->getPlatformKind(), version);
923+
};
924+
if (introducedVersion)
925+
mutableAttr->setRawIntroduced(canonicalizeVersion(*introducedVersion));
926+
927+
if (deprecatedVersion)
928+
mutableAttr->setRawDeprecated(canonicalizeVersion(*deprecatedVersion));
929+
930+
if (obsoletedVersion)
931+
mutableAttr->setRawObsoleted(canonicalizeVersion(*obsoletedVersion));
932+
}
933+
934+
return semanticAttr;
935+
}
936+
797937
AvailabilityRange
798938
SemanticAvailableAttr::getIntroducedRange(const ASTContext &Ctx) const {
799939
assert(getDomain().isActive(Ctx));

lib/Sema/TypeCheckAttr.cpp

Lines changed: 0 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -8373,143 +8373,6 @@ ValueDecl *RenamedDeclRequest::evaluate(Evaluator &evaluator,
83738373
return renamedDecl;
83748374
}
83758375

8376-
static std::optional<AvailabilityDomain>
8377-
getAvailabilityDomainForName(Identifier identifier,
8378-
const DeclContext *declContext) {
8379-
if (auto builtinDomain = AvailabilityDomain::builtinDomainForString(
8380-
identifier.str(), declContext))
8381-
return builtinDomain;
8382-
8383-
auto &ctx = declContext->getASTContext();
8384-
if (auto customDomain =
8385-
ctx.MainModule->getAvailabilityDomainForIdentifier(identifier))
8386-
return customDomain;
8387-
8388-
return std::nullopt;
8389-
}
8390-
8391-
std::optional<SemanticAvailableAttr>
8392-
SemanticAvailableAttrRequest::evaluate(swift::Evaluator &evaluator,
8393-
const AvailableAttr *attr,
8394-
const Decl *decl) const {
8395-
if (attr->hasCachedDomain())
8396-
return SemanticAvailableAttr(attr);
8397-
8398-
auto &ctx = decl->getASTContext();
8399-
auto &diags = ctx.Diags;
8400-
auto attrLoc = attr->getLocation();
8401-
auto attrName = attr->getAttrName();
8402-
auto domainLoc = attr->getDomainLoc();
8403-
auto introducedVersion = attr->getRawIntroduced();
8404-
auto deprecatedVersion = attr->getRawDeprecated();
8405-
auto obsoletedVersion = attr->getRawObsoleted();
8406-
auto mutableAttr = const_cast<AvailableAttr *>(attr);
8407-
auto domain = attr->getCachedDomain();
8408-
8409-
if (!domain) {
8410-
auto domainIdentifier = attr->getDomainIdentifier();
8411-
ASSERT(domainIdentifier);
8412-
8413-
// Attempt to resolve the domain specified for the attribute and diagnose
8414-
// if no domain is found.
8415-
auto declContext = decl->getInnermostDeclContext();
8416-
domain = getAvailabilityDomainForName(*domainIdentifier, declContext);
8417-
if (!domain) {
8418-
auto domainString = domainIdentifier->str();
8419-
if (auto suggestion = closestCorrectedPlatformString(domainString)) {
8420-
diags
8421-
.diagnose(domainLoc, diag::attr_availability_suggest_platform,
8422-
domainString, attrName, *suggestion)
8423-
.fixItReplace(SourceRange(domainLoc), *suggestion);
8424-
} else {
8425-
diags.diagnose(attrLoc, diag::attr_availability_unknown_platform,
8426-
domainString, attrName);
8427-
}
8428-
return std::nullopt;
8429-
}
8430-
8431-
if (domain->isCustom() &&
8432-
!ctx.LangOpts.hasFeature(Feature::CustomAvailability) &&
8433-
!declContext->isInSwiftinterface()) {
8434-
diags.diagnose(domainLoc,
8435-
diag::attr_availability_requires_custom_availability,
8436-
domain->getNameForAttributePrinting(), attr);
8437-
return std::nullopt;
8438-
}
8439-
8440-
mutableAttr->setCachedDomain(*domain);
8441-
}
8442-
8443-
auto domainName = domain->getNameForAttributePrinting();
8444-
auto semanticAttr = SemanticAvailableAttr(attr);
8445-
8446-
bool hasVersionSpec =
8447-
(introducedVersion || deprecatedVersion || obsoletedVersion);
8448-
8449-
if (!domain->isVersioned() && hasVersionSpec) {
8450-
SourceRange versionSourceRange;
8451-
if (introducedVersion)
8452-
versionSourceRange = semanticAttr.getIntroducedSourceRange();
8453-
else if (deprecatedVersion)
8454-
versionSourceRange = semanticAttr.getDeprecatedSourceRange();
8455-
else if (obsoletedVersion)
8456-
versionSourceRange = semanticAttr.getObsoletedSourceRange();
8457-
8458-
diags
8459-
.diagnose(attrLoc, diag::attr_availability_unexpected_version, attr,
8460-
domainName)
8461-
.highlight(versionSourceRange);
8462-
return std::nullopt;
8463-
}
8464-
8465-
if (domain->isSwiftLanguage() || domain->isPackageDescription()) {
8466-
switch (attr->getKind()) {
8467-
case AvailableAttr::Kind::Deprecated:
8468-
diags.diagnose(attrLoc,
8469-
diag::attr_availability_expected_deprecated_version,
8470-
attrName, domainName);
8471-
return std::nullopt;
8472-
8473-
case AvailableAttr::Kind::Unavailable:
8474-
diags.diagnose(attrLoc, diag::attr_availability_cannot_be_used_for_domain,
8475-
"unavailable", attrName, domainName);
8476-
return std::nullopt;
8477-
8478-
case AvailableAttr::Kind::NoAsync:
8479-
diags.diagnose(attrLoc, diag::attr_availability_cannot_be_used_for_domain,
8480-
"noasync", attrName, domainName);
8481-
return std::nullopt;
8482-
8483-
case AvailableAttr::Kind::Default:
8484-
break;
8485-
}
8486-
8487-
if (!hasVersionSpec) {
8488-
diags.diagnose(attrLoc, diag::attr_availability_expected_version_spec,
8489-
attrName, domainName);
8490-
return std::nullopt;
8491-
}
8492-
}
8493-
8494-
// Canonicalize platform versions.
8495-
// FIXME: [availability] This should be done when remapping versions instead.
8496-
if (domain->isPlatform()) {
8497-
auto canonicalizeVersion = [&](llvm::VersionTuple version) {
8498-
return canonicalizePlatformVersion(domain->getPlatformKind(), version);
8499-
};
8500-
if (introducedVersion)
8501-
mutableAttr->setRawIntroduced(canonicalizeVersion(*introducedVersion));
8502-
8503-
if (deprecatedVersion)
8504-
mutableAttr->setRawDeprecated(canonicalizeVersion(*deprecatedVersion));
8505-
8506-
if (obsoletedVersion)
8507-
mutableAttr->setRawObsoleted(canonicalizeVersion(*obsoletedVersion));
8508-
}
8509-
8510-
return semanticAttr;
8511-
}
8512-
85138376
template <typename ATTR>
85148377
static void forEachCustomAttribute(
85158378
Decl *decl,

0 commit comments

Comments
 (0)