@@ -793,6 +793,19 @@ DiagnosticBehavior SendableCheckContext::diagnosticBehavior(
793
793
return defaultBehavior;
794
794
}
795
795
796
+ static bool shouldDiagnosePreconcurrencyImports (SourceFile &sf) {
797
+ switch (sf.Kind ) {
798
+ case SourceFileKind::Interface:
799
+ case SourceFileKind::SIL:
800
+ return false ;
801
+
802
+ case SourceFileKind::Library:
803
+ case SourceFileKind::Main:
804
+ case SourceFileKind::MacroExpansion:
805
+ return true ;
806
+ }
807
+ }
808
+
796
809
bool swift::diagnoseSendabilityErrorBasedOn (
797
810
NominalTypeDecl *nominal, SendableCheckContext fromContext,
798
811
llvm::function_ref<bool (DiagnosticBehavior)> diagnose) {
@@ -806,49 +819,70 @@ bool swift::diagnoseSendabilityErrorBasedOn(
806
819
807
820
bool wasSuppressed = diagnose (behavior);
808
821
809
- bool emittedDiagnostics =
810
- behavior != DiagnosticBehavior::Ignore && !wasSuppressed;
811
-
812
- // When the type is explicitly Sendable *or* explicitly non-Sendable, we
813
- // assume it has been audited and `@preconcurrency` is not recommended even
814
- // though it would actually affect the diagnostic.
815
- bool nominalIsImportedAndHasImplicitSendability =
816
- nominal &&
817
- nominal->getParentModule () != fromContext.fromDC ->getParentModule () &&
818
- !hasExplicitSendableConformance (nominal);
819
-
820
- if (emittedDiagnostics && nominalIsImportedAndHasImplicitSendability) {
821
- // This type was imported from another module; try to find the
822
- // corresponding import.
823
- Optional<AttributedImport<swift::ImportedModule>> import;
824
- SourceFile *sourceFile = fromContext.fromDC ->getParentSourceFile ();
825
- if (sourceFile) {
826
- import = findImportFor (nominal, fromContext.fromDC );
827
- }
828
-
829
- // If we found the import that makes this nominal type visible, remark
830
- // that it can be @preconcurrency import.
831
- // Only emit this remark once per source file, because it can happen a
832
- // lot.
833
- if (import && !import->options .contains (ImportFlags::Preconcurrency) &&
834
- import->importLoc .isValid () && sourceFile &&
835
- !sourceFile->hasImportUsedPreconcurrency (*import)) {
836
- SourceLoc importLoc = import->importLoc ;
837
- ASTContext &ctx = nominal->getASTContext ();
822
+ SourceFile *sourceFile = fromContext.fromDC ->getParentSourceFile ();
823
+ if (sourceFile && shouldDiagnosePreconcurrencyImports (*sourceFile)) {
824
+ bool emittedDiagnostics =
825
+ behavior != DiagnosticBehavior::Ignore && !wasSuppressed;
826
+
827
+ // When the type is explicitly Sendable *or* explicitly non-Sendable, we
828
+ // assume it has been audited and `@preconcurrency` is not recommended even
829
+ // though it would actually affect the diagnostic.
830
+ bool nominalIsImportedAndHasImplicitSendability =
831
+ nominal &&
832
+ nominal->getParentModule () != fromContext.fromDC ->getParentModule () &&
833
+ !hasExplicitSendableConformance (nominal);
834
+
835
+ if (emittedDiagnostics && nominalIsImportedAndHasImplicitSendability) {
836
+ // This type was imported from another module; try to find the
837
+ // corresponding import.
838
+ Optional<AttributedImport<swift::ImportedModule>> import =
839
+ findImportFor (nominal, fromContext.fromDC );
840
+
841
+ // If we found the import that makes this nominal type visible, remark
842
+ // that it can be @preconcurrency import.
843
+ // Only emit this remark once per source file, because it can happen a
844
+ // lot.
845
+ if (import && !import->options .contains (ImportFlags::Preconcurrency) &&
846
+ import->importLoc .isValid () && sourceFile &&
847
+ !sourceFile->hasImportUsedPreconcurrency (*import)) {
848
+ SourceLoc importLoc = import->importLoc ;
849
+ ASTContext &ctx = nominal->getASTContext ();
838
850
839
- ctx.Diags . diagnose (
840
- importLoc, diag::add_predates_concurrency_import,
841
- ctx.LangOpts .isSwiftVersionAtLeast (6 ),
842
- nominal->getParentModule ()->getName ())
843
- .fixItInsert (importLoc, " @preconcurrency " );
851
+ ctx.Diags
852
+ . diagnose ( importLoc, diag::add_predates_concurrency_import,
853
+ ctx.LangOpts .isSwiftVersionAtLeast (6 ),
854
+ nominal->getParentModule ()->getName ())
855
+ .fixItInsert (importLoc, " @preconcurrency " );
844
856
845
- sourceFile->setImportUsedPreconcurrency (*import);
857
+ sourceFile->setImportUsedPreconcurrency (*import);
858
+ }
846
859
}
847
860
}
848
861
849
862
return behavior == DiagnosticBehavior::Unspecified && !wasSuppressed;
850
863
}
851
864
865
+ void swift::diagnoseUnnecessaryPreconcurrencyImports (SourceFile &sf) {
866
+ if (!shouldDiagnosePreconcurrencyImports (sf))
867
+ return ;
868
+
869
+ ASTContext &ctx = sf.getASTContext ();
870
+
871
+ if (ctx.TypeCheckerOpts .SkipFunctionBodies != FunctionBodySkipping::None)
872
+ return ;
873
+
874
+ for (const auto &import : sf.getImports ()) {
875
+ if (import.options .contains (ImportFlags::Preconcurrency) &&
876
+ import.importLoc .isValid () &&
877
+ !sf.hasImportUsedPreconcurrency (import)) {
878
+ ctx.Diags .diagnose (
879
+ import.importLoc , diag::remove_predates_concurrency_import,
880
+ import.module .importedModule ->getName ())
881
+ .fixItRemove (import.preconcurrencyRange );
882
+ }
883
+ }
884
+ }
885
+
852
886
// / Produce a diagnostic for a single instance of a non-Sendable type where
853
887
// / a Sendable type is required.
854
888
static bool diagnoseSingleNonSendableType (
0 commit comments