Skip to content

Sema: Clean up some availability type checking APIs #80043

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
Mar 16, 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
40 changes: 18 additions & 22 deletions lib/Sema/TypeCheckAvailability.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,13 +288,6 @@ static bool shouldTreatDeclContextAsAsyncForDiagnostics(const DeclContext *DC) {
return DC->isAsyncContext();
}

AvailabilityRange TypeChecker::overApproximateAvailabilityAtLocation(
SourceLoc loc, const DeclContext *DC,
const AvailabilityScope **MostRefined) {
return AvailabilityContext::forLocation(loc, DC, MostRefined)
.getPlatformRange();
}

/// A class that walks the AST to find the innermost (i.e., deepest) node that
/// contains a target SourceRange and matches a particular criterion.
/// This class finds the innermost nodes of interest by walking
Expand Down Expand Up @@ -689,8 +682,8 @@ static bool fixAvailabilityByNarrowingNearbyVersionCheck(
return false;

const AvailabilityScope *scope = nullptr;
(void)TypeChecker::overApproximateAvailabilityAtLocation(ReferenceRange.Start,
ReferenceDC, &scope);
(void)AvailabilityContext::forLocation(ReferenceRange.Start, ReferenceDC,
&scope);
if (!scope)
return false;

Expand Down Expand Up @@ -866,7 +859,7 @@ static void diagnosePotentialUnavailability(
// FIXME: [availability] Should this take an AvailabilityContext instead of
// AvailabilityRange?
bool TypeChecker::checkAvailability(SourceRange ReferenceRange,
AvailabilityRange RequiredAvailability,
AvailabilityRange PlatformRange,
const DeclContext *ReferenceDC,
llvm::function_ref<InFlightDiagnostic(
AvailabilityDomain, AvailabilityRange)>
Expand All @@ -880,24 +873,25 @@ bool TypeChecker::checkAvailability(SourceRange ReferenceRange,
return false;

auto availabilityAtLocation =
TypeChecker::overApproximateAvailabilityAtLocation(ReferenceRange.Start,
ReferenceDC);
if (!availabilityAtLocation.isContainedIn(RequiredAvailability)) {
AvailabilityContext::forLocation(ReferenceRange.Start, ReferenceDC)
.getPlatformRange();

if (!availabilityAtLocation.isContainedIn(PlatformRange)) {
diagnosePotentialUnavailability(ReferenceRange, Diagnose, ReferenceDC,
domain, RequiredAvailability);
domain, PlatformRange);
return true;
}

return false;
}

bool TypeChecker::checkAvailability(
SourceRange ReferenceRange, AvailabilityRange RequiredAvailability,
SourceRange ReferenceRange, AvailabilityRange PlatformRange,
Diag<AvailabilityDomain, AvailabilityRange> Diag,
const DeclContext *ReferenceDC) {
auto &Diags = ReferenceDC->getASTContext().Diags;
return TypeChecker::checkAvailability(
ReferenceRange, RequiredAvailability, ReferenceDC,
ReferenceRange, PlatformRange, ReferenceDC,
[&](AvailabilityDomain domain, AvailabilityRange range) {
return Diags.diagnose(ReferenceRange.Start, Diag, domain, range);
});
Expand Down Expand Up @@ -1494,18 +1488,19 @@ static void diagnoseIfDeprecated(SourceRange ReferenceRange,
if (!Attr)
return;

auto Availability = Where.getAvailability();

// We match the behavior of clang to not report deprecation warnings
// inside declarations that are themselves deprecated on all deployment
// targets.
if (Where.isDeprecated()) {
if (Availability.isDeprecated()) {
return;
}

auto *ReferenceDC = Where.getDeclContext();
auto &Context = ReferenceDC->getASTContext();
if (!Context.LangOpts.DisableAvailabilityChecking) {
AvailabilityRange RunningOSVersions = Where.getAvailabilityRange();
if (RunningOSVersions.isKnownUnreachable()) {
if (Availability.getPlatformRange().isKnownUnreachable()) {
// Suppress a deprecation warning if the availability checking machinery
// thinks the reference program location will not execute on any
// deployment target for the current platform.
Expand Down Expand Up @@ -1573,18 +1568,19 @@ static bool diagnoseIfDeprecated(SourceLoc loc,
if (!attr)
return false;

auto availability = where.getAvailability();

// We match the behavior of clang to not report deprecation warnings
// inside declarations that are themselves deprecated on all deployment
// targets.
if (where.isDeprecated()) {
if (availability.isDeprecated()) {
return false;
}

auto *dc = where.getDeclContext();
auto &ctx = dc->getASTContext();
if (!ctx.LangOpts.DisableAvailabilityChecking) {
AvailabilityRange runningOSVersion = where.getAvailabilityRange();
if (runningOSVersion.isKnownUnreachable()) {
if (availability.getPlatformRange().isKnownUnreachable()) {
// Suppress a deprecation warning if the availability checking machinery
// thinks the reference program location will not execute on any
// deployment target for the current platform.
Expand Down
8 changes: 0 additions & 8 deletions lib/Sema/TypeCheckAvailability.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,6 @@ class ExportContext {

AvailabilityContext getAvailability() const { return Availability; }

AvailabilityRange getAvailabilityRange() const {
return Availability.getPlatformRange();
}

/// If not 'None', the context has the inlinable function body restriction.
FragileFunctionKind getFragileFunctionKind() const { return FragileKind; }

Expand All @@ -188,10 +184,6 @@ class ExportContext {
/// or declarations from `@_implementationOnly` imports.
bool isExported() const { return Exported; }

/// If true, the context is part of a deprecated declaration and can
/// reference other deprecated declarations without warning.
bool isDeprecated() const { return Availability.isDeprecated(); }

/// If true, the context can only reference exported declarations, either
/// because it is the signature context of an exported declaration, or
/// because it is the function body context of an inlinable function.
Expand Down
8 changes: 3 additions & 5 deletions lib/Sema/TypeCheckConcurrency.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,9 +220,8 @@ bool IsDefaultActorRequest::evaluate(
auto customExecutorAvailability =
ctx.getConcurrencyDistributedActorWithCustomExecutorAvailability();

auto actorAvailability = TypeChecker::overApproximateAvailabilityAtLocation(
classDecl->getStartLoc(),
classDecl);
auto actorAvailability =
AvailabilityContext::forDeclSignature(classDecl).getPlatformRange();

if (!actorAvailability.isContainedIn(customExecutorAvailability)) {
// Any 'distributed actor' declared with availability lower than the
Expand Down Expand Up @@ -1510,8 +1509,7 @@ void swift::tryDiagnoseExecutorConformance(ASTContext &C,
AvailabilityRange requirementInfo =
AvailabilityInference::availableRange(moveOnlyEnqueueRequirement);
AvailabilityRange declInfo =
TypeChecker::overApproximateAvailabilityAtLocation(
nominal->getLoc(), dyn_cast<DeclContext>(nominal));
AvailabilityContext::forDeclSignature(nominal).getPlatformRange();
canRemoveOldDecls = declInfo.isContainedIn(requirementInfo);
}

Expand Down
2 changes: 1 addition & 1 deletion lib/Sema/TypeCheckDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1732,7 +1732,7 @@ bool TypeChecker::isAvailabilitySafeForConformance(
requirementInfo.constrainWith(infoForConformingDecl);

AvailabilityRange infoForProtocolDecl =
overApproximateAvailabilityAtLocation(proto->getLoc(), proto);
AvailabilityContext::forDeclSignature(proto).getPlatformRange();

witnessInfo.constrainWith(infoForProtocolDecl);
requirementInfo.constrainWith(infoForProtocolDecl);
Expand Down
6 changes: 3 additions & 3 deletions lib/Sema/TypeCheckProtocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1904,7 +1904,7 @@ RequirementCheck WitnessChecker::checkWitness(ValueDecl *requirement,
isDefaultWitness = isa<ProtocolDecl>(nominal);
if (isDefaultWitness && match.Witness->isDeprecated() &&
!requirement->isDeprecated()) {
auto conformanceContext = ExportContext::forConformance(DC, Proto);
auto conformanceContext = AvailabilityContext::forDeclSignature(DC->getInnermostDeclarationDeclContext());
if (!conformanceContext.isDeprecated()) {
return RequirementCheck(CheckKind::DefaultWitnessDeprecated);
}
Expand Down Expand Up @@ -5210,8 +5210,8 @@ static void ensureRequirementsAreSatisfied(ASTContext &ctx,
if (auto depMemberType = depTy->getAs<DependentMemberType>()) {
auto assocType = depMemberType->getAssocType();
availability.intersectWith(
TypeChecker::overApproximateAvailabilityAtLocation(
assocType->getLoc(), assocType->getDeclContext()));
AvailabilityContext::forDeclSignature(assocType)
.getPlatformRange());
}

diagnoseConformanceAvailability(
Expand Down
3 changes: 2 additions & 1 deletion lib/Sema/TypeCheckStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3299,7 +3299,8 @@ FuncDecl *TypeChecker::getForEachIteratorNextFunction(

// We can only call next(isolation:) if we are in an availability context
// that supports typed throws.
auto availability = overApproximateAvailabilityAtLocation(loc, dc);
auto availability =
AvailabilityContext::forLocation(loc, dc).getPlatformRange();
if (availability.isContainedIn(ctx.getTypedThrowsAvailability()))
return nextElement;

Expand Down
12 changes: 2 additions & 10 deletions lib/Sema/TypeChecker.h
Original file line number Diff line number Diff line change
Expand Up @@ -1031,14 +1031,6 @@ bool isAvailabilitySafeForConformance(
const ValueDecl *witness, const DeclContext *dc,
AvailabilityRange &requiredAvailability);

/// Returns an over-approximation of the range of operating system versions
/// that could the passed-in location could be executing upon for
/// the target platform. If MostRefined != nullptr, set to the most-refined
/// scope found while approximating.
AvailabilityRange overApproximateAvailabilityAtLocation(
SourceLoc loc, const DeclContext *DC,
const AvailabilityScope **MostRefined = nullptr);

/// Returns a diagnostic indicating why the declaration cannot be annotated
/// with an @available() attribute indicating it is potentially unavailable
/// or None if this is allowed.
Expand All @@ -1055,7 +1047,7 @@ diagnosticIfDeclCannotBeUnavailable(const Decl *D, SemanticAvailableAttr attr);
/// platform are available at the given `SourceRange`. If not, `Diagnose` is
/// invoked.
bool checkAvailability(SourceRange ReferenceRange,
AvailabilityRange RequiredAvailability,
AvailabilityRange PlatformRange,
const DeclContext *ReferenceDC,
llvm::function_ref<InFlightDiagnostic(AvailabilityDomain,
AvailabilityRange)>
Expand All @@ -1065,7 +1057,7 @@ bool checkAvailability(SourceRange ReferenceRange,
/// platform are available at the given `SourceRange`. If not, `Diag` is
/// emitted.
bool checkAvailability(SourceRange ReferenceRange,
AvailabilityRange RequiredAvailability,
AvailabilityRange PlatformRange,
Diag<AvailabilityDomain, AvailabilityRange> Diag,
const DeclContext *ReferenceDC);

Expand Down