@@ -6263,20 +6263,56 @@ void TypeChecker::checkConformancesInContext(IterableDeclContext *idc) {
62636263 // protocol, just warn; we'll pick up the original conformance.
62646264 auto existingModule = diag.ExistingDC ->getParentModule ();
62656265 auto extendedNominal = diag.ExistingDC ->getSelfNominalTypeDecl ();
6266- if (existingModule != dc ->getParentModule () &&
6267- (existingModule-> getName () = =
6268- extendedNominal-> getParentModule () ->getName () ||
6266+ auto definingModule = extendedNominal ->getParentModule ()-> getName ();
6267+ bool conformanceInOrigModule =
6268+ (existingModule ->getName () == definingModule ||
62696269 existingModule == diag.Protocol ->getParentModule () ||
6270- existingModule->getName ().is (" CoreGraphics" ))) {
6270+ existingModule->getName ().is (" CoreGraphics" ));
6271+
6272+ // Redundant Sendable conformances are always warnings.
6273+ auto knownProtocol = diag.Protocol ->getKnownProtocolKind ();
6274+ bool isSendable = knownProtocol == KnownProtocolKind::Sendable;
6275+ // Try to find an inherited Sendable conformance if there is one.
6276+ if (isSendable && !SendableConformance) {
6277+ SmallVector<ProtocolConformance *, 2 > conformances;
6278+ nominal->lookupConformance (diag.Protocol , conformances);
6279+ for (auto conformance : conformances) {
6280+ if (isa<InheritedProtocolConformance>(conformance))
6281+ SendableConformance = conformance;
6282+ }
6283+ }
6284+
6285+ if ((existingModule != dc->getParentModule () && conformanceInOrigModule) ||
6286+ isSendable) {
62716287 // Warn about the conformance.
6272- auto diagID = differentlyConditional
6273- ? diag::redundant_conformance_adhoc_conditional
6274- : diag::redundant_conformance_adhoc;
6275- Context.Diags .diagnose (diag.Loc , diagID, dc->getDeclaredInterfaceType (),
6276- diag.Protocol ->getName (),
6277- existingModule->getName () ==
6278- extendedNominal->getParentModule ()->getName (),
6279- existingModule->getName ());
6288+ if (isSendable && SendableConformance &&
6289+ isa<InheritedProtocolConformance>(SendableConformance)) {
6290+ // Allow re-stated unchecked conformances to Sendable in subclasses
6291+ // as long as the inherited conformance isn't unavailable.
6292+ auto *conformance = SendableConformance->getRootConformance ();
6293+ auto *decl = conformance->getDeclContext ()->getAsDecl ();
6294+ if (!AvailableAttr::isUnavailable (decl)) {
6295+ continue ;
6296+ }
6297+
6298+ Context.Diags .diagnose (diag.Loc , diag::unavailable_conformance,
6299+ nominal->getDeclaredInterfaceType (),
6300+ diag.Protocol ->getName ());
6301+ } else if (existingModule == dc->getParentModule ()) {
6302+ Context.Diags .diagnose (diag.Loc , diag::redundant_conformance,
6303+ nominal->getDeclaredInterfaceType (),
6304+ diag.Protocol ->getName ())
6305+ .limitBehavior (DiagnosticBehavior::Warning);
6306+ } else {
6307+ auto diagID = differentlyConditional
6308+ ? diag::redundant_conformance_adhoc_conditional
6309+ : diag::redundant_conformance_adhoc;
6310+ Context.Diags .diagnose (diag.Loc , diagID, dc->getDeclaredInterfaceType (),
6311+ diag.Protocol ->getName (),
6312+ existingModule->getName () ==
6313+ extendedNominal->getParentModule ()->getName (),
6314+ existingModule->getName ());
6315+ }
62806316
62816317 // Complain about any declarations in this extension whose names match
62826318 // a requirement in that protocol.
0 commit comments