@@ -770,10 +770,17 @@ DiagnosticBehavior SendableCheckContext::defaultDiagnosticBehavior() const {
770
770
return defaultSendableDiagnosticBehavior (fromDC->getASTContext ().LangOpts );
771
771
}
772
772
773
- // / Determine whether the given nominal type that is within the current module
774
- // / has an explicit Sendable.
775
- static bool hasExplicitSendableConformance (NominalTypeDecl *nominal) {
773
+ // / Determine whether the given nominal type has an explicit Sendable
774
+ // / conformance (regardless of its availability).
775
+ static bool hasExplicitSendableConformance (NominalTypeDecl *nominal,
776
+ bool applyModuleDefault = true ) {
776
777
ASTContext &ctx = nominal->getASTContext ();
778
+ auto nominalModule = nominal->getParentModule ();
779
+
780
+ // In a concurrency-checked module, a missing conformance is equivalent to
781
+ // an explicitly unavailable one. If we want to apply this rule, do so now.
782
+ if (applyModuleDefault && nominalModule->isConcurrencyChecked ())
783
+ return true ;
777
784
778
785
// Look for any conformance to `Sendable`.
779
786
auto proto = ctx.getProtocol (KnownProtocolKind::Sendable);
@@ -782,7 +789,7 @@ static bool hasExplicitSendableConformance(NominalTypeDecl *nominal) {
782
789
783
790
// Look for a conformance. If it's present and not (directly) missing,
784
791
// we're done.
785
- auto conformance = nominal-> getParentModule () ->lookupConformance (
792
+ auto conformance = nominalModule ->lookupConformance (
786
793
nominal->getDeclaredInterfaceType (), proto, /* allowMissing=*/ true );
787
794
return conformance &&
788
795
!(isa<BuiltinProtocolConformance>(conformance.getConcrete ()) &&
@@ -826,18 +833,13 @@ static Optional<AttributedImport<ImportedModule>> findImportFor(
826
833
// / nominal type.
827
834
DiagnosticBehavior SendableCheckContext::diagnosticBehavior (
828
835
NominalTypeDecl *nominal) const {
829
- // Determine whether the type was explicitly non-Sendable.
830
- auto nominalModule = nominal->getParentModule ();
831
- bool isExplicitlyNonSendable = nominalModule->isConcurrencyChecked () ||
832
- hasExplicitSendableConformance (nominal);
833
-
834
836
// Determine whether this nominal type is visible via a @preconcurrency
835
837
// import.
836
838
auto import = findImportFor (nominal, fromDC);
839
+ auto sourceFile = fromDC->getParentSourceFile ();
837
840
838
841
// When the type is explicitly non-Sendable...
839
- auto sourceFile = fromDC->getParentSourceFile ();
840
- if (isExplicitlyNonSendable) {
842
+ if (hasExplicitSendableConformance (nominal)) {
841
843
// @preconcurrency imports downgrade the diagnostic to a warning in Swift 6,
842
844
if (import && import ->options .contains (ImportFlags::Preconcurrency)) {
843
845
if (sourceFile)
@@ -857,7 +859,7 @@ DiagnosticBehavior SendableCheckContext::diagnosticBehavior(
857
859
if (sourceFile)
858
860
sourceFile->setImportUsedPreconcurrency (*import );
859
861
860
- return nominalModule ->getASTContext ().LangOpts .isSwiftVersionAtLeast (6 )
862
+ return nominal ->getASTContext ().LangOpts .isSwiftVersionAtLeast (6 )
861
863
? DiagnosticBehavior::Warning
862
864
: DiagnosticBehavior::Ignore;
863
865
}
@@ -917,29 +919,34 @@ static bool diagnoseSingleNonSendableType(
917
919
diag::non_sendable_nominal, nominal->getDescriptiveKind (),
918
920
nominal->getName ());
919
921
920
- // This type was imported from another module; try to find the
921
- // corresponding import.
922
- Optional<AttributedImport<swift::ImportedModule>> import ;
923
- SourceFile *sourceFile = fromContext.fromDC ->getParentSourceFile ();
924
- if (sourceFile) {
925
- import = findImportFor (nominal, fromContext.fromDC );
926
- }
922
+ // When the type is explicitly Sendable *or* explicitly non-Sendable, we
923
+ // assume it has been audited and `@preconcurrency` is not recommended even
924
+ // though it would actually affect the diagnostic.
925
+ if (!hasExplicitSendableConformance (nominal)) {
926
+ // This type was imported from another module; try to find the
927
+ // corresponding import.
928
+ Optional<AttributedImport<swift::ImportedModule>> import ;
929
+ SourceFile *sourceFile = fromContext.fromDC ->getParentSourceFile ();
930
+ if (sourceFile) {
931
+ import = findImportFor (nominal, fromContext.fromDC );
932
+ }
927
933
928
- // If we found the import that makes this nominal type visible, remark
929
- // that it can be @preconcurrency import.
930
- // Only emit this remark once per source file, because it can happen a
931
- // lot.
932
- if (import && !import ->options .contains (ImportFlags::Preconcurrency) &&
933
- import ->importLoc .isValid () && sourceFile &&
934
- !sourceFile->hasImportUsedPreconcurrency (*import )) {
935
- SourceLoc importLoc = import ->importLoc ;
936
- ctx.Diags .diagnose (
937
- importLoc, diag::add_predates_concurrency_import,
938
- ctx.LangOpts .isSwiftVersionAtLeast (6 ),
939
- nominal->getParentModule ()->getName ())
940
- .fixItInsert (importLoc, " @preconcurrency " );
934
+ // If we found the import that makes this nominal type visible, remark
935
+ // that it can be @preconcurrency import.
936
+ // Only emit this remark once per source file, because it can happen a
937
+ // lot.
938
+ if (import && !import ->options .contains (ImportFlags::Preconcurrency) &&
939
+ import ->importLoc .isValid () && sourceFile &&
940
+ !sourceFile->hasImportUsedPreconcurrency (*import )) {
941
+ SourceLoc importLoc = import ->importLoc ;
942
+ ctx.Diags .diagnose (
943
+ importLoc, diag::add_predates_concurrency_import,
944
+ ctx.LangOpts .isSwiftVersionAtLeast (6 ),
945
+ nominal->getParentModule ()->getName ())
946
+ .fixItInsert (importLoc, " @preconcurrency " );
941
947
942
- sourceFile->setImportUsedPreconcurrency (*import );
948
+ sourceFile->setImportUsedPreconcurrency (*import );
949
+ }
943
950
}
944
951
}
945
952
@@ -1156,7 +1163,7 @@ void swift::diagnoseMissingExplicitSendable(NominalTypeDecl *nominal) {
1156
1163
return ;
1157
1164
1158
1165
// If the conformance is explicitly stated, do nothing.
1159
- if (hasExplicitSendableConformance (nominal))
1166
+ if (hasExplicitSendableConformance (nominal, /* applyModuleDefault= */ false ))
1160
1167
return ;
1161
1168
1162
1169
// Diagnose it.
0 commit comments