@@ -835,41 +835,52 @@ DiagnosticBehavior SendableCheckContext::diagnosticBehavior(
835835}
836836
837837std::optional<DiagnosticBehavior>
838- SendableCheckContext::preconcurrencyBehavior (Decl *decl) const {
839- if (!decl)
840- return std::nullopt ;
838+ swift::getConcurrencyDiagnosticBehaviorLimit (NominalTypeDecl *nominal,
839+ const DeclContext *fromDC,
840+ bool ignoreExplicitConformance) {
841+ ModuleDecl *importedModule = nullptr ;
842+ if (nominal->getAttrs ().hasAttribute <PreconcurrencyAttr>()) {
843+ // If the declaration itself has the @preconcurrency attribute,
844+ // respect it.
845+ importedModule = nominal->getParentModule ();
846+ } else {
847+ // Determine whether this nominal type is visible via a @preconcurrency
848+ // import.
849+ auto import = nominal->findImport (fromDC);
850+ auto sourceFile = fromDC->getParentSourceFile ();
841851
842- if (auto *nominal = dyn_cast<NominalTypeDecl>(decl)) {
843- ModuleDecl *importedModule = nullptr ;
844- if (nominal->getAttrs ().hasAttribute <PreconcurrencyAttr>()) {
845- // If the declaration itself has the @preconcurrency attribute,
846- // respect it.
847- importedModule = nominal->getParentModule ();
848- } else {
849- // Determine whether this nominal type is visible via a @preconcurrency
850- // import.
851- auto import = nominal->findImport (fromDC);
852- auto sourceFile = fromDC->getParentSourceFile ();
852+ if (!import || !import ->options .contains (ImportFlags::Preconcurrency))
853+ return std::nullopt ;
853854
854- if (! import || ! import -> options . contains (ImportFlags::Preconcurrency) )
855- return std:: nullopt ;
855+ if (sourceFile )
856+ sourceFile-> setImportUsedPreconcurrency (* import ) ;
856857
857- if (sourceFile)
858- sourceFile-> setImportUsedPreconcurrency (* import );
858+ importedModule = import -> module . importedModule ;
859+ }
859860
860- importedModule = import ->module .importedModule ;
861- }
861+ // When the type is explicitly non-Sendable, @preconcurrency imports
862+ // downgrade the diagnostic to a warning in Swift 6.
863+ if (!ignoreExplicitConformance &&
864+ hasExplicitSendableConformance (nominal))
865+ return DiagnosticBehavior::Warning;
862866
863- // When the type is explicitly non-Sendable, @preconcurrency imports
864- // downgrade the diagnostic to a warning in Swift 6.
865- if (hasExplicitSendableConformance (nominal))
866- return DiagnosticBehavior::Warning;
867+ // When the type is implicitly non-Sendable, `@preconcurrency` suppresses
868+ // diagnostics until the imported module enables Swift 6.
869+ return importedModule->isConcurrencyChecked ()
870+ ? DiagnosticBehavior::Warning
871+ : DiagnosticBehavior::Ignore;
872+ }
873+
874+ std::optional<DiagnosticBehavior>
875+ SendableCheckContext::preconcurrencyBehavior (
876+ Decl *decl,
877+ bool ignoreExplicitConformance) const {
878+ if (!decl)
879+ return std::nullopt ;
867880
868- // When the type is implicitly non-Sendable, `@preconcurrency` suppresses
869- // diagnostics until the imported module enables Swift 6.
870- return importedModule->isConcurrencyChecked ()
871- ? DiagnosticBehavior::Warning
872- : DiagnosticBehavior::Ignore;
881+ if (auto *nominal = dyn_cast<NominalTypeDecl>(decl)) {
882+ return getConcurrencyDiagnosticBehaviorLimit (nominal, fromDC,
883+ ignoreExplicitConformance);
873884 }
874885
875886 return std::nullopt ;
@@ -5841,8 +5852,16 @@ bool swift::checkSendableConformance(
58415852
58425853 // Sendable can only be used in the same source file.
58435854 auto conformanceDecl = conformanceDC->getAsDecl ();
5844- auto behavior = SendableCheckContext (conformanceDC, check)
5845- .defaultDiagnosticBehavior ();
5855+ SendableCheckContext checkContext (conformanceDC, check);
5856+ DiagnosticBehavior behavior = checkContext.defaultDiagnosticBehavior ();
5857+ if (conformance->getSourceKind () == ConformanceEntryKind::Implied &&
5858+ conformance->getProtocol ()->isSpecificProtocol (
5859+ KnownProtocolKind::Sendable)) {
5860+ if (auto optBehavior = checkContext.preconcurrencyBehavior (
5861+ nominal, /* ignoreExplicitConformance=*/ true ))
5862+ behavior = *optBehavior;
5863+ }
5864+
58465865 if (conformanceDC->getOutermostParentSourceFile () &&
58475866 conformanceDC->getOutermostParentSourceFile () !=
58485867 nominal->getOutermostParentSourceFile ()) {
0 commit comments