Skip to content

Commit 9ebc4ca

Browse files
committed
[Type checker] Warn about unavailable witnesses used to satisfy a requirement.
1 parent 515f3ef commit 9ebc4ca

File tree

3 files changed

+36
-1
lines changed

3 files changed

+36
-1
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1533,6 +1533,10 @@ NOTE(declared_protocol_conformance_here,none,
15331533
"%0 implicitly conforms to protocol %2}1 here",
15341534
(Type, unsigned, DeclName, DeclName))
15351535

1536+
WARNING(witness_unavailable,none,
1537+
"unavailable %0 %1 was used to satisfy a requirement of protocol %2",
1538+
(DescriptiveDeclKind, DeclName, DeclName))
1539+
15361540
ERROR(redundant_conformance,none,
15371541
"redundant conformance of %0 to protocol %1", (Type, DeclName))
15381542

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,9 @@ namespace {
274274
/// The witness is a constructor which is more failable than the
275275
/// requirement.
276276
ConstructorFailability,
277+
278+
/// The witness itself is inaccessible.
279+
WitnessUnavailable,
277280
};
278281

279282
/// Describes an optional adjustment made to a witness.
@@ -1539,6 +1542,11 @@ checkWitness(AccessScope requiredAccessScope,
15391542
}
15401543
}
15411544

1545+
if (match.Witness->getAttrs().isUnavailable(TC.Context) &&
1546+
!requirement->getAttrs().isUnavailable(TC.Context)) {
1547+
return CheckKind::WitnessUnavailable;
1548+
}
1549+
15421550
return CheckKind::Success;
15431551
}
15441552

@@ -2905,7 +2913,7 @@ ConformanceChecker::resolveWitnessViaLookup(ValueDecl *requirement) {
29052913
auto ctor = cast<ConstructorDecl>(requirement);
29062914
auto witnessCtor = cast<ConstructorDecl>(witness);
29072915
auto &diags = witness->getASTContext().Diags;
2908-
diags.diagnose(witness->getLoc(),
2916+
diags.diagnose(witness,
29092917
diag::witness_initializer_failability,
29102918
ctor->getFullName(),
29112919
witnessCtor->getFailability()
@@ -2914,6 +2922,19 @@ ConformanceChecker::resolveWitnessViaLookup(ValueDecl *requirement) {
29142922
});
29152923

29162924
break;
2925+
2926+
case CheckKind::WitnessUnavailable:
2927+
diagnoseOrDefer(requirement, /*isError=*/false,
2928+
[witness, requirement](NormalProtocolConformance *conformance) {
2929+
auto &diags = witness->getASTContext().Diags;
2930+
diags.diagnose(witness, diag::witness_unavailable,
2931+
witness->getDescriptiveKind(),
2932+
witness->getFullName(),
2933+
conformance->getProtocol()->getFullName());
2934+
diags.diagnose(requirement, diag::protocol_requirement_here,
2935+
requirement->getFullName());
2936+
});
2937+
break;
29172938
}
29182939

29192940
ClassDecl *classDecl = Adoptee->getClassOrBoundGenericClass();

test/decl/protocol/req/unavailable.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,13 @@ class Bar : NonObjCProto { // expected-error {{type 'Bar' does not conform to pr
2323
func good() {}
2424
}
2525

26+
27+
// Warn about unavailable witnesses.
28+
protocol P {
29+
func foo(bar: Foo) // expected-note{{requirement 'foo(bar:)' declared here}}
30+
}
31+
32+
struct ConformsToP : P {
33+
@available(*, unavailable)
34+
func foo(bar: Foo) { } // expected-warning{{unavailable instance method 'foo(bar:)' was used to satisfy a requirement of protocol 'P'}}
35+
}

0 commit comments

Comments
 (0)