@@ -734,16 +734,6 @@ static bool shouldDiagnoseExistingDataRaces(const DeclContext *dc) {
734734 });
735735}
736736
737- // / Determine the default diagnostic behavior for this language mode.
738- static DiagnosticBehavior defaultSendableDiagnosticBehavior (
739- const LangOptions &langOpts) {
740- // Prior to Swift 6, all Sendable-related diagnostics are warnings at most.
741- if (!langOpts.isSwiftVersionAtLeast (6 ))
742- return DiagnosticBehavior::Warning;
743-
744- return DiagnosticBehavior::Unspecified;
745- }
746-
747737bool SendableCheckContext::isExplicitSendableConformance () const {
748738 if (!conformanceCheck)
749739 return false ;
@@ -766,7 +756,7 @@ DiagnosticBehavior SendableCheckContext::defaultDiagnosticBehavior() const {
766756 !shouldDiagnoseExistingDataRaces (fromDC))
767757 return DiagnosticBehavior::Ignore;
768758
769- return defaultSendableDiagnosticBehavior (fromDC-> getASTContext (). LangOpts ) ;
759+ return DiagnosticBehavior::Warning ;
770760}
771761
772762DiagnosticBehavior
@@ -856,38 +846,8 @@ findImportFor(const DeclContext *dc, const DeclContext *fromDC) {
856846// / nominal type.
857847DiagnosticBehavior SendableCheckContext::diagnosticBehavior (
858848 NominalTypeDecl *nominal) const {
859- // Determine whether this nominal type is visible via a @preconcurrency
860- // import.
861- auto import = findImportFor (nominal, fromDC);
862- auto sourceFile = fromDC->getParentSourceFile ();
863-
864- // When the type is explicitly non-Sendable...
865- if (hasExplicitSendableConformance (nominal)) {
866- // @preconcurrency imports downgrade the diagnostic to a warning in Swift 6,
867- if (import && import ->options .contains (ImportFlags::Preconcurrency)) {
868- if (sourceFile)
869- sourceFile->setImportUsedPreconcurrency (*import );
870-
871- return DiagnosticBehavior::Warning;
872- }
873-
874- return defaultSendableDiagnosticBehavior (fromDC->getASTContext ().LangOpts );
875- }
876-
877- // When the type is implicitly non-Sendable...
878-
879- // @preconcurrency suppresses the diagnostic in Swift 5.x, and
880- // downgrades it to a warning in Swift 6 and later.
881- if (import && import ->options .contains (ImportFlags::Preconcurrency)) {
882- if (sourceFile)
883- sourceFile->setImportUsedPreconcurrency (*import );
884-
885- // `@preconcurrency` suppresses diagnostics until the imported
886- // module enables Swift 6.
887- return import ->module .importedModule ->isConcurrencyChecked ()
888- ? DiagnosticBehavior::Warning
889- : DiagnosticBehavior::Ignore;
890- }
849+ if (hasExplicitSendableConformance (nominal))
850+ return DiagnosticBehavior::Warning;
891851
892852 DiagnosticBehavior defaultBehavior = implicitSendableDiagnosticBehavior ();
893853
@@ -902,6 +862,38 @@ DiagnosticBehavior SendableCheckContext::diagnosticBehavior(
902862 return defaultBehavior;
903863}
904864
865+ llvm::Optional<DiagnosticBehavior>
866+ SendableCheckContext::preconcurrencyBehavior (Decl *decl) const {
867+ if (!decl)
868+ return llvm::None;
869+
870+ if (auto *nominal = dyn_cast<NominalTypeDecl>(decl)) {
871+ // Determine whether this nominal type is visible via a @preconcurrency
872+ // import.
873+ auto import = findImportFor (nominal, fromDC);
874+ auto sourceFile = fromDC->getParentSourceFile ();
875+
876+ if (!import || !import ->options .contains (ImportFlags::Preconcurrency))
877+ return llvm::None;
878+
879+ if (sourceFile)
880+ sourceFile->setImportUsedPreconcurrency (*import );
881+
882+ // When the type is explicitly non-Sendable, @preconcurrency imports
883+ // downgrade the diagnostic to a warning in Swift 6.
884+ if (hasExplicitSendableConformance (nominal))
885+ return DiagnosticBehavior::Warning;
886+
887+ // When the type is implicitly non-Sendable, `@preconcurrency` suppresses
888+ // diagnostics until the imported module enables Swift 6.
889+ return import ->module .importedModule ->isConcurrencyChecked ()
890+ ? DiagnosticBehavior::Warning
891+ : DiagnosticBehavior::Ignore;
892+ }
893+
894+ return llvm::None;
895+ }
896+
905897static bool shouldDiagnosePreconcurrencyImports (SourceFile &sf) {
906898 switch (sf.Kind ) {
907899 case SourceFileKind::Interface:
@@ -2106,7 +2098,8 @@ namespace {
21062098
21072099 // / Note when the enclosing context could be put on a global actor.
21082100 // FIXME: This should handle closures too.
2109- static bool missingGlobalActorOnContext (DeclContext *dc, Type globalActor, DiagnosticBehavior behavior) {
2101+ static bool missingGlobalActorOnContext (DeclContext *dc, Type globalActor,
2102+ DiagnosticBehavior behavior) {
21102103 // If we are in a synchronous function on the global actor,
21112104 // suggest annotating with the global actor itself.
21122105 if (auto fn = findAnnotatableFunction (dc)) {
@@ -2125,13 +2118,19 @@ namespace {
21252118 return false ;
21262119
21272120 case ActorIsolation::Unspecified:
2121+ if (behavior != DiagnosticBehavior::Note) {
2122+ fn->diagnose (diag::invalid_isolated_calls_in_body,
2123+ globalActor->getWithoutParens ().getString (), fn)
2124+ .limitBehaviorUntilSwiftVersion (behavior, 6 );
2125+ }
2126+
2127+ // Always emit the note with fix-it.
21282128 fn->diagnose (diag::add_globalactor_to_function,
21292129 globalActor->getWithoutParens ().getString (),
21302130 fn, globalActor)
2131- .limitBehavior (behavior)
2132- .fixItInsert (fn->getAttributeInsertionLoc (false ),
2133- diag::insert_globalactor_attr, globalActor);
2134- return true ;
2131+ .fixItInsert (fn->getAttributeInsertionLoc (false ),
2132+ diag::insert_globalactor_attr, globalActor);
2133+ return true ;
21352134 }
21362135 }
21372136 }
@@ -2163,7 +2162,7 @@ namespace {
21632162 // Diagnose actor_isolated_non_self_reference as note
21642163 // if fix-it provided in missingGlobalActorOnContext
21652164 ctx.Diags .diagnose (error.loc , error.diag )
2166- .limitBehavior (behavior);
2165+ .limitBehaviorUntilSwiftVersion (behavior, 6 );
21672166 }
21682167 }
21692168
@@ -2188,7 +2187,7 @@ namespace {
21882187 // Diagnose actor_isolated_call as note if
21892188 // fix-it provided in missingGlobalActorOnContext
21902189 ctx.Diags .diagnose (error.loc , error.diag )
2191- .limitBehavior (behavior);
2190+ .limitBehaviorUntilSwiftVersion (behavior, 6 );
21922191 }
21932192 }
21942193
@@ -3012,12 +3011,21 @@ namespace {
30123011 import && import ->options .contains (ImportFlags::Preconcurrency);
30133012 const auto isPreconcurrencyUnspecifiedIsolation =
30143013 isPreconcurrencyImport && isolation.isUnspecified ();
3014+
3015+ // If the global variable is preconcurrency without an explicit
3016+ // isolation, ignore the warning. Otherwise, limit the behavior
3017+ // to a warning until Swift 6.
3018+ DiagnosticBehavior limit;
3019+ if (isPreconcurrencyUnspecifiedIsolation) {
3020+ limit = DiagnosticBehavior::Ignore;
3021+ } else {
3022+ limit = DiagnosticBehavior::Warning;
3023+ }
3024+
30153025 ctx.Diags .diagnose (loc, diag::shared_mutable_state_access, value)
3016- .warnUntilSwiftVersionIf (!isPreconcurrencyUnspecifiedIsolation, 6 )
3017- .limitBehaviorIf (isPreconcurrencyImport, DiagnosticBehavior::Warning)
3018- .limitBehaviorIf (!ctx.isSwiftVersionAtLeast (6 ) &&
3019- isPreconcurrencyUnspecifiedIsolation,
3020- DiagnosticBehavior::Ignore);
3026+ .limitBehaviorUntilSwiftVersion (limit, 6 )
3027+ // Preconcurrency global variables are warnings even in Swift 6
3028+ .limitBehaviorIf (isPreconcurrencyImport, DiagnosticBehavior::Warning);
30213029 value->diagnose (diag::kind_declared_here, value->getDescriptiveKind ());
30223030 if (const auto sourceFile = getDeclContext ()->getParentSourceFile ();
30233031 sourceFile && isPreconcurrencyImport) {
@@ -5248,7 +5256,7 @@ void swift::checkOverrideActorIsolation(ValueDecl *value) {
52485256 value->diagnose (
52495257 diag::actor_isolation_override_mismatch, isolation,
52505258 value, overriddenIsolation)
5251- .limitBehavior (behavior);
5259+ .limitBehaviorUntilSwiftVersion (behavior, 6 );
52525260 overridden->diagnose (diag::overridden_here);
52535261}
52545262
@@ -5346,7 +5354,7 @@ static bool checkSendableInstanceStorage(
53465354 && SendableCheckContext (dc, check)
53475355 .defaultDiagnosticBehavior () != DiagnosticBehavior::Ignore) {
53485356 sd->diagnose (diag::sendable_raw_storage, sd->getName ())
5349- .limitBehavior (behavior);
5357+ .limitBehaviorUntilSwiftVersion (behavior, 6 );
53505358 }
53515359 return true ;
53525360 }
@@ -5381,7 +5389,7 @@ static bool checkSendableInstanceStorage(
53815389 property
53825390 ->diagnose (diag::concurrent_value_class_mutable_property,
53835391 property->getName (), nominal)
5384- .limitBehavior (behavior);
5392+ .limitBehaviorUntilSwiftVersion (behavior, 6 );
53855393 }
53865394 invalid = invalid || (behavior == DiagnosticBehavior::Unspecified);
53875395 return true ;
@@ -5393,10 +5401,13 @@ static bool checkSendableInstanceStorage(
53935401 }
53945402
53955403 // Check that the property type is Sendable.
5404+ SendableCheckContext context (dc, check);
53965405 diagnoseNonSendableTypes (
5397- propertyType, SendableCheckContext (dc, check) ,
5406+ propertyType, context ,
53985407 /* inDerivedConformance*/ Type (), property->getLoc (),
53995408 [&](Type type, DiagnosticBehavior behavior) {
5409+ auto preconcurrency =
5410+ context.preconcurrencyBehavior (type->getAnyNominal ());
54005411 if (isImplicitSendableCheck (check)) {
54015412 // If this is for an externally-visible conformance, fail.
54025413 if (check == SendableCheck::ImplicitForExternallyVisible) {
@@ -5405,8 +5416,9 @@ static bool checkSendableInstanceStorage(
54055416 }
54065417
54075418 // If we are to ignore this diagnostic, just continue.
5408- if (behavior == DiagnosticBehavior::Ignore)
5409- return false ;
5419+ if (behavior == DiagnosticBehavior::Ignore ||
5420+ preconcurrency == DiagnosticBehavior::Ignore)
5421+ return true ;
54105422
54115423 invalid = true ;
54125424 return true ;
@@ -5415,7 +5427,8 @@ static bool checkSendableInstanceStorage(
54155427 property->diagnose (diag::non_concurrent_type_member,
54165428 propertyType, false , property->getName (),
54175429 nominal)
5418- .limitBehavior (behavior);
5430+ .limitBehaviorUntilSwiftVersion (behavior, 6 )
5431+ .limitBehaviorIf (preconcurrency);
54195432 return false ;
54205433 });
54215434
@@ -5430,10 +5443,13 @@ static bool checkSendableInstanceStorage(
54305443
54315444 // / Handle an enum associated value.
54325445 bool operator ()(EnumElementDecl *element, Type elementType) override {
5446+ SendableCheckContext context (dc, check);
54335447 diagnoseNonSendableTypes (
5434- elementType, SendableCheckContext (dc, check) ,
5448+ elementType, context ,
54355449 /* inDerivedConformance*/ Type (), element->getLoc (),
54365450 [&](Type type, DiagnosticBehavior behavior) {
5451+ auto preconcurrency =
5452+ context.preconcurrencyBehavior (elementType->getAnyNominal ());
54375453 if (isImplicitSendableCheck (check)) {
54385454 // If this is for an externally-visible conformance, fail.
54395455 if (check == SendableCheck::ImplicitForExternallyVisible) {
@@ -5442,7 +5458,8 @@ static bool checkSendableInstanceStorage(
54425458 }
54435459
54445460 // If we are to ignore this diagnostic, just continue.
5445- if (behavior == DiagnosticBehavior::Ignore)
5461+ if (behavior == DiagnosticBehavior::Ignore ||
5462+ preconcurrency == DiagnosticBehavior::Ignore)
54465463 return false ;
54475464
54485465 invalid = true ;
@@ -5451,7 +5468,8 @@ static bool checkSendableInstanceStorage(
54515468
54525469 element->diagnose (diag::non_concurrent_type_member, type,
54535470 true , element->getName (), nominal)
5454- .limitBehavior (behavior);
5471+ .limitBehaviorUntilSwiftVersion (behavior, 6 )
5472+ .limitBehaviorIf (preconcurrency);
54555473 return false ;
54565474 });
54575475
@@ -5510,7 +5528,7 @@ bool swift::checkSendableConformance(
55105528 nominal->getOutermostParentSourceFile ()) {
55115529 conformanceDecl->diagnose (diag::concurrent_value_outside_source_file,
55125530 nominal)
5513- .limitBehavior (behavior);
5531+ .limitBehaviorUntilSwiftVersion (behavior, 6 );
55145532
55155533 if (behavior == DiagnosticBehavior::Unspecified)
55165534 return true ;
@@ -5523,7 +5541,7 @@ bool swift::checkSendableConformance(
55235541 if (!classDecl->isSemanticallyFinal ()) {
55245542 classDecl->diagnose (diag::concurrent_value_nonfinal_class,
55255543 classDecl->getName ())
5526- .limitBehavior (behavior);
5544+ .limitBehaviorUntilSwiftVersion (behavior, 6 );
55275545
55285546 if (behavior == DiagnosticBehavior::Unspecified)
55295547 return true ;
@@ -5538,7 +5556,7 @@ bool swift::checkSendableConformance(
55385556 ->diagnose (diag::concurrent_value_inherit,
55395557 nominal->getASTContext ().LangOpts .EnableObjCInterop ,
55405558 classDecl->getName ())
5541- .limitBehavior (behavior);
5559+ .limitBehaviorUntilSwiftVersion (behavior, 6 );
55425560
55435561 if (behavior == DiagnosticBehavior::Unspecified)
55445562 return true ;
0 commit comments