Skip to content

Commit d2d572e

Browse files
committed
Sema: Reword diagnostics about potentially unavailable decls to improve clarity for authors of API libraries. When decls are diagnosed as potentially unavailable on an OS earlier than the deployment target, the message will now indicate that the issue would be faced by clients of the module.
Resolves rdar://93466875
1 parent 42655e1 commit d2d572e

File tree

3 files changed

+115
-84
lines changed

3 files changed

+115
-84
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5547,9 +5547,13 @@ 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 to clients of %1 in %2 %3 or newer",
5552+
(DeclName, ModuleDecl *, StringRef, llvm::VersionTuple))
5553+
5554+
WARNING(availability_decl_only_version_newer_for_clients_warn, none,
5555+
"%0 is only available to clients of %1 in %2 %3 or newer",
5556+
(DeclName, ModuleDecl *, StringRef, llvm::VersionTuple))
55535557

55545558
ERROR(availability_opaque_types_only_version_newer, none,
55555559
"'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+
const bool RequiredVersionIsDeploymentTargetOrLower =
1981+
Version <= AvailabilityContext::forDeploymentTarget(Context)
1982+
.getOSVersion()
1983+
.getLowerEndpoint();
1984+
1985+
if (RequiredVersionIsDeploymentTargetOrLower) {
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(), ReferenceDC->getParentModule(), Platform, Version);
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)