Skip to content

[5.7] Soften new unavailable conformance diagnostics #42540

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
Apr 22, 2022
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
9 changes: 9 additions & 0 deletions lib/AST/DeclContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/SaveAndRestore.h"
#include "clang/AST/ASTContext.h"
using namespace swift;

#define DEBUG_TYPE "Name lookup"
Expand Down Expand Up @@ -734,6 +735,14 @@ unsigned DeclContext::printContext(raw_ostream &OS, const unsigned indent,
}
}

if (auto decl = getAsDecl())
if (decl->getClangNode().getLocation().isValid()) {
auto &clangSM = getASTContext().getClangModuleLoader()
->getClangASTContext().getSourceManager();
OS << " clang_loc=";
decl->getClangNode().getLocation().print(OS, clangSM);
}

if (!onlyAPartialLine)
OS << "\n";
return Depth + 1;
Expand Down
8 changes: 6 additions & 2 deletions lib/Sema/ResilienceDiagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,8 @@ bool
TypeChecker::diagnoseConformanceExportability(SourceLoc loc,
const RootProtocolConformance *rootConf,
const ExtensionDecl *ext,
const ExportContext &where) {
const ExportContext &where,
bool useConformanceAvailabilityErrorsOption) {
if (!where.mustOnlyReferenceExportedDecls())
return false;

Expand All @@ -178,6 +179,9 @@ TypeChecker::diagnoseConformanceExportability(SourceLoc loc,
rootConf->getProtocol()->getName(),
static_cast<unsigned>(*reason),
M->getName(),
static_cast<unsigned>(originKind));
static_cast<unsigned>(originKind))
.warnUntilSwiftVersionIf(useConformanceAvailabilityErrorsOption &&
!ctx.LangOpts.EnableConformanceAvailabilityErrors,
6);
return true;
}
29 changes: 20 additions & 9 deletions lib/Sema/TypeCheckAvailability.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2584,7 +2584,8 @@ bool swift::diagnoseExplicitUnavailability(const ValueDecl *D, SourceRange R,
bool swift::diagnoseExplicitUnavailability(SourceLoc loc,
const RootProtocolConformance *rootConf,
const ExtensionDecl *ext,
const ExportContext &where) {
const ExportContext &where,
bool useConformanceAvailabilityErrorsOption) {
auto *attr = AvailableAttr::isUnavailable(ext);
if (!attr)
return false;
Expand Down Expand Up @@ -2641,7 +2642,10 @@ bool swift::diagnoseExplicitUnavailability(SourceLoc loc,
diags.diagnose(loc, diag::conformance_availability_unavailable,
type, proto,
platform.empty(), platform, EncodedMessage.Message)
.limitBehavior(behavior);
.limitBehavior(behavior)
.warnUntilSwiftVersionIf(useConformanceAvailabilityErrorsOption &&
!ctx.LangOpts.EnableConformanceAvailabilityErrors,
6);

switch (attr->getVersionAvailability(ctx)) {
case AvailableVersionComparison::Available:
Expand Down Expand Up @@ -2995,7 +2999,8 @@ class ExprAvailabilityWalker : public ASTWalker {

if (auto EE = dyn_cast<ErasureExpr>(E)) {
for (ProtocolConformanceRef C : EE->getConformances()) {
diagnoseConformanceAvailability(E->getLoc(), C, Where);
diagnoseConformanceAvailability(E->getLoc(), C, Where, Type(), Type(),
/*useConformanceAvailabilityErrorsOpt=*/true);
}
}

Expand Down Expand Up @@ -3791,7 +3796,8 @@ bool
swift::diagnoseConformanceAvailability(SourceLoc loc,
ProtocolConformanceRef conformance,
const ExportContext &where,
Type depTy, Type replacementTy) {
Type depTy, Type replacementTy,
bool useConformanceAvailabilityErrorsOption) {
assert(!where.isImplicit());

if (!conformance.isConcrete())
Expand Down Expand Up @@ -3825,12 +3831,14 @@ swift::diagnoseConformanceAvailability(SourceLoc loc,
};

if (auto *ext = dyn_cast<ExtensionDecl>(rootConf->getDeclContext())) {
if (TypeChecker::diagnoseConformanceExportability(loc, rootConf, ext, where)) {
if (TypeChecker::diagnoseConformanceExportability(loc, rootConf, ext, where,
useConformanceAvailabilityErrorsOption)) {
maybeEmitAssociatedTypeNote();
return true;
}

if (diagnoseExplicitUnavailability(loc, rootConf, ext, where)) {
if (diagnoseExplicitUnavailability(loc, rootConf, ext, where,
useConformanceAvailabilityErrorsOption)) {
maybeEmitAssociatedTypeNote();
return true;
}
Expand Down Expand Up @@ -3858,7 +3866,8 @@ swift::diagnoseConformanceAvailability(SourceLoc loc,
SubstitutionMap subConformanceSubs =
concreteConf->getSubstitutions(DC->getParentModule());
if (diagnoseSubstitutionMapAvailability(loc, subConformanceSubs, where,
depTy, replacementTy))
depTy, replacementTy,
useConformanceAvailabilityErrorsOption))
return true;

return false;
Expand All @@ -3868,11 +3877,13 @@ bool
swift::diagnoseSubstitutionMapAvailability(SourceLoc loc,
SubstitutionMap subs,
const ExportContext &where,
Type depTy, Type replacementTy) {
Type depTy, Type replacementTy,
bool useConformanceAvailabilityErrorsOption) {
bool hadAnyIssues = false;
for (ProtocolConformanceRef conformance : subs.getConformances()) {
if (diagnoseConformanceAvailability(loc, conformance, where,
depTy, replacementTy))
depTy, replacementTy,
useConformanceAvailabilityErrorsOption))
hadAnyIssues = true;
}
return hadAnyIssues;
Expand Down
9 changes: 6 additions & 3 deletions lib/Sema/TypeCheckAvailability.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,14 +220,16 @@ diagnoseConformanceAvailability(SourceLoc loc,
ProtocolConformanceRef conformance,
const ExportContext &context,
Type depTy=Type(),
Type replacementTy=Type());
Type replacementTy=Type(),
bool useConformanceAvailabilityErrorsOption = false);

bool
diagnoseSubstitutionMapAvailability(SourceLoc loc,
SubstitutionMap subs,
const ExportContext &context,
Type depTy=Type(),
Type replacementTy=Type());
Type replacementTy=Type(),
bool useConformanceAvailabilityErrorsOption = false);

/// Diagnose uses of unavailable declarations. Returns true if a diagnostic
/// was emitted.
Expand Down Expand Up @@ -261,7 +263,8 @@ bool diagnoseExplicitUnavailability(
SourceLoc loc,
const RootProtocolConformance *rootConf,
const ExtensionDecl *ext,
const ExportContext &where);
const ExportContext &where,
bool useConformanceAvailabilityErrorsOption = false);

/// Check if \p decl has a introduction version required by -require-explicit-availability
void checkExplicitAvailability(Decl *decl);
Expand Down
3 changes: 2 additions & 1 deletion lib/Sema/TypeChecker.h
Original file line number Diff line number Diff line change
Expand Up @@ -1002,7 +1002,8 @@ bool diagnoseDeclRefExportability(SourceLoc loc,
bool diagnoseConformanceExportability(SourceLoc loc,
const RootProtocolConformance *rootConf,
const ExtensionDecl *ext,
const ExportContext &where);
const ExportContext &where,
bool useConformanceAvailabilityErrorsOpt = false);

/// \name Availability checking
///
Expand Down
30 changes: 30 additions & 0 deletions test/Sema/conformance_availability_warn.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,33 @@ func passAvailableConformance1a(x: HasAvailableConformance1) {
_ = x.isGalloping
_ = UsesHorse<HasAvailableConformance1>.self
}

// Explicit unavailability
public struct HasAvailableConformance2 {}

@available(*, unavailable)
extension HasAvailableConformance2 : Horse {} // expected-note 6 {{conformance of 'HasAvailableConformance2' to 'Horse' has been explicitly marked unavailable here}}

// Some availability diagnostics become warnings in Swift 5 mode without
// -enable-conformance-availability-errors because they were incorrectly
// accepted before and rejecting them would break source compatibility. Others
// are unaffected because they have always been rejected.

func passAvailableConformance2(x: HasAvailableConformance2) {
takesHorse(x) // expected-error {{conformance of 'HasAvailableConformance2' to 'Horse' is unavailable}}
takesHorseExistential(x) // expected-warning {{conformance of 'HasAvailableConformance2' to 'Horse' is unavailable; this is an error in Swift 6}}
x.giddyUp() // expected-error {{conformance of 'HasAvailableConformance2' to 'Horse' is unavailable}}
_ = x.isGalloping // expected-error {{conformance of 'HasAvailableConformance2' to 'Horse' is unavailable}}
_ = x[keyPath: \.isGalloping] // expected-error {{conformance of 'HasAvailableConformance2' to 'Horse' is unavailable}}
_ = UsesHorse<HasAvailableConformance2>.self // expected-error {{conformance of 'HasAvailableConformance2' to 'Horse' is unavailable}}
}

@available(*, unavailable)
func passAvailableConformance2a(x: HasAvailableConformance2) {
takesHorse(x)
takesHorseExistential(x)
x.giddyUp()
_ = x.isGalloping
_ = UsesHorse<HasAvailableConformance2>.self
}