@@ -835,41 +835,52 @@ DiagnosticBehavior SendableCheckContext::diagnosticBehavior(
835
835
}
836
836
837
837
std::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 ();
841
851
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;
853
854
854
- if (! import || ! import -> options . contains (ImportFlags::Preconcurrency) )
855
- return std::nullopt ;
855
+ if (sourceFile )
856
+ sourceFile-> setImportUsedPreconcurrency (* import ) ;
856
857
857
- if (sourceFile)
858
- sourceFile-> setImportUsedPreconcurrency (* import );
858
+ importedModule = import -> module . importedModule ;
859
+ }
859
860
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;
862
866
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;
867
880
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);
873
884
}
874
885
875
886
return std::nullopt;
@@ -5841,8 +5852,16 @@ bool swift::checkSendableConformance(
5841
5852
5842
5853
// Sendable can only be used in the same source file.
5843
5854
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
+
5846
5865
if (conformanceDC->getOutermostParentSourceFile () &&
5847
5866
conformanceDC->getOutermostParentSourceFile () !=
5848
5867
nominal->getOutermostParentSourceFile ()) {
0 commit comments