Skip to content

Commit 62edd18

Browse files
committed
Ensure that we diagnose unavailable Sendable conformances in Sendable checking
1 parent 89fd6e3 commit 62edd18

File tree

2 files changed

+30
-25
lines changed

2 files changed

+30
-25
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,29 @@ static void addSendableFixIt(
573573
}
574574
}
575575

576+
/// Determine whether there is an unavailable conformance here.
577+
static bool hasUnavailableConformance(ProtocolConformanceRef conformance) {
578+
// Abstract conformances are never unavailable.
579+
if (!conformance.isConcrete())
580+
return false;
581+
582+
// Check whether this conformance is on an unavailable extension.
583+
auto concrete = conformance.getConcrete();
584+
auto ext = dyn_cast<ExtensionDecl>(concrete->getDeclContext());
585+
if (ext && AvailableAttr::isUnavailable(ext))
586+
return true;
587+
588+
// Check the conformances in the substitution map.
589+
auto module = concrete->getDeclContext()->getParentModule();
590+
auto subMap = concrete->getSubstitutions(module);
591+
for (auto subConformance : subMap.getConformances()) {
592+
if (hasUnavailableConformance(subConformance))
593+
return true;
594+
}
595+
596+
return false;
597+
}
598+
576599
/// Produce a diagnostic for a single instance of a non-Sendable type where
577600
/// a Sendable type is required.
578601
static bool diagnoseSingleNonSendableType(
@@ -647,8 +670,9 @@ bool swift::diagnoseNonSendableTypes(
647670
if (!proto)
648671
return false;
649672

673+
// FIXME: More detail for unavailable conformances.
650674
auto conformance = TypeChecker::conformsToProtocol(type, proto, module);
651-
if (conformance.isInvalid()) {
675+
if (conformance.isInvalid() || hasUnavailableConformance(conformance)) {
652676
return diagnoseSingleNonSendableType(type, module, loc, diagnose);
653677
}
654678

@@ -730,29 +754,6 @@ void swift::diagnoseMissingSendableConformance(
730754
}
731755

732756
namespace {
733-
/// Determine whether there is an unavailable conformance here.
734-
static bool hasUnavailableConformance(ProtocolConformanceRef conformance) {
735-
// Abstract conformances are never unavailable.
736-
if (!conformance.isConcrete())
737-
return false;
738-
739-
// Check whether this conformance is on an unavailable extension.
740-
auto concrete = conformance.getConcrete();
741-
auto ext = dyn_cast<ExtensionDecl>(concrete->getDeclContext());
742-
if (ext && AvailableAttr::isUnavailable(ext))
743-
return true;
744-
745-
// Check the conformances in the substitution map.
746-
auto module = concrete->getDeclContext()->getParentModule();
747-
auto subMap = concrete->getSubstitutions(module);
748-
for (auto subConformance : subMap.getConformances()) {
749-
if (hasUnavailableConformance(subConformance))
750-
return true;
751-
}
752-
753-
return false;
754-
}
755-
756757
template<typename Visitor>
757758
bool visitInstanceStorage(
758759
NominalTypeDecl *nominal, DeclContext *dc, Visitor &visitor);

test/Concurrency/require-explicit-sendable.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ extension S6: Sendable where T: Sendable, U: Sendable { }
5858
func acceptSendable<T: Sendable>(_: T) {
5959
}
6060

61-
struct S7 {
61+
struct S7 { // FIXME: expected-note{{consider making struct 'S7' conform to the 'Sendable' protocol}}
6262
}
6363

6464
@available(*, unavailable)
@@ -93,3 +93,7 @@ public struct S10 { // expected-warning{{public struct 'S10' does not specify wh
9393
// expected-note@-2{{make struct 'S10' explicitly non-Sendable to suppress this warning}}
9494
var s7: S7
9595
}
96+
97+
struct S11: Sendable {
98+
var s7: S7 // expected-error{{stored property 's7' of 'Sendable'-conforming struct 'S11' has non-sendable type 'S7'}}
99+
}

0 commit comments

Comments
 (0)