Skip to content

Commit b52257e

Browse files
authored
Merge pull request swiftlang#58963 from tshortli/diagnose-potentially-unavailable-to-clients-of-module
Sema: Improve availability diagnostics when `-target-min-inlining-version min` is specified
2 parents 0e8ece6 + a0bf64f commit b52257e

File tree

3 files changed

+327
-268
lines changed

3 files changed

+327
-268
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5547,9 +5547,15 @@ ERROR(availability_decl_only_version_newer, none,
55475547
"%0 is only available in %1 %2 or newer",
55485548
(DeclName, StringRef, llvm::VersionTuple))
55495549

5550-
WARNING(availability_decl_only_version_newer_warn, none,
5551-
"%0 is only available in %1 %2 or newer",
5552-
(DeclName, StringRef, llvm::VersionTuple))
5550+
ERROR(availability_decl_only_version_newer_for_clients, none,
5551+
"%0 is only available in %1 %2 or newer; clients of %3 may have a lower"
5552+
" deployment target",
5553+
(DeclName, StringRef, llvm::VersionTuple, ModuleDecl *))
5554+
5555+
WARNING(availability_decl_only_version_newer_for_clients_warn, none,
5556+
"%0 is only available in %1 %2 or newer; clients of %3 may have a lower"
5557+
" deployment target",
5558+
(DeclName, StringRef, llvm::VersionTuple, ModuleDecl *))
55535559

55545560
ERROR(availability_opaque_types_only_version_newer, none,
55555561
"'some' return types are only available in %0 %1 or newer",

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1967,36 +1967,58 @@ void TypeChecker::checkConcurrencyAvailability(SourceRange ReferenceRange,
19671967
}
19681968
}
19691969

1970+
/// Returns the diagnostic to emit for the potentially unavailable decl and sets
1971+
/// \p IsError accordingly.
1972+
static Diagnostic getPotentialUnavailabilityDiagnostic(
1973+
const ValueDecl *D, const DeclContext *ReferenceDC,
1974+
const UnavailabilityReason &Reason, bool WarnBeforeDeploymentTarget,
1975+
bool &IsError) {
1976+
ASTContext &Context = ReferenceDC->getASTContext();
1977+
auto Platform = prettyPlatformString(targetPlatform(Context.LangOpts));
1978+
auto Version = Reason.getRequiredOSVersionRange().getLowerEndpoint();
1979+
1980+
if (Version <= AvailabilityContext::forDeploymentTarget(Context)
1981+
.getOSVersion()
1982+
.getLowerEndpoint()) {
1983+
// The required OS version is at or before the deployment target so this
1984+
// diagnostic should indicate that the decl could be unavailable to clients
1985+
// of the module containing the reference.
1986+
IsError = !WarnBeforeDeploymentTarget;
1987+
1988+
return Diagnostic(
1989+
IsError ? diag::availability_decl_only_version_newer_for_clients
1990+
: diag::availability_decl_only_version_newer_for_clients_warn,
1991+
D->getName(), Platform, Version, ReferenceDC->getParentModule());
1992+
}
1993+
1994+
IsError = true;
1995+
return Diagnostic(diag::availability_decl_only_version_newer, D->getName(),
1996+
Platform, Version);
1997+
}
1998+
19701999
bool TypeChecker::diagnosePotentialUnavailability(
19712000
const ValueDecl *D, SourceRange ReferenceRange,
19722001
const DeclContext *ReferenceDC,
19732002
const UnavailabilityReason &Reason,
19742003
bool WarnBeforeDeploymentTarget) {
19752004
ASTContext &Context = ReferenceDC->getASTContext();
19762005

1977-
bool AsError = true;
19782006
auto RequiredRange = Reason.getRequiredOSVersionRange();
2007+
bool IsError;
19792008
{
1980-
if (WarnBeforeDeploymentTarget &&
1981-
!RequiredRange.isContainedIn(
1982-
AvailabilityContext::forDeploymentTarget(Context).getOSVersion()))
1983-
AsError = false;
1984-
19852009
auto Diag = Context.Diags.diagnose(
19862010
ReferenceRange.Start,
1987-
AsError ? diag::availability_decl_only_version_newer
1988-
: diag::availability_decl_only_version_newer_warn,
1989-
D->getName(), prettyPlatformString(targetPlatform(Context.LangOpts)),
1990-
Reason.getRequiredOSVersionRange().getLowerEndpoint());
2011+
getPotentialUnavailabilityDiagnostic(
2012+
D, ReferenceDC, Reason, WarnBeforeDeploymentTarget, IsError));
19912013

19922014
// Direct a fixit to the error if an existing guard is nearly-correct
19932015
if (fixAvailabilityByNarrowingNearbyVersionCheck(
19942016
ReferenceRange, ReferenceDC, RequiredRange, Context, Diag))
1995-
return AsError;
2017+
return IsError;
19962018
}
19972019

19982020
fixAvailability(ReferenceRange, ReferenceDC, RequiredRange, Context);
1999-
return AsError;
2021+
return IsError;
20002022
}
20012023

20022024
void TypeChecker::diagnosePotentialAccessorUnavailability(

0 commit comments

Comments
 (0)