@@ -734,16 +734,6 @@ static bool shouldDiagnoseExistingDataRaces(const DeclContext *dc) {
734
734
});
735
735
}
736
736
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
-
747
737
bool SendableCheckContext::isExplicitSendableConformance () const {
748
738
if (!conformanceCheck)
749
739
return false ;
@@ -766,7 +756,7 @@ DiagnosticBehavior SendableCheckContext::defaultDiagnosticBehavior() const {
766
756
!shouldDiagnoseExistingDataRaces (fromDC))
767
757
return DiagnosticBehavior::Ignore;
768
758
769
- return defaultSendableDiagnosticBehavior (fromDC-> getASTContext (). LangOpts ) ;
759
+ return DiagnosticBehavior::Warning ;
770
760
}
771
761
772
762
DiagnosticBehavior
@@ -856,38 +846,8 @@ findImportFor(const DeclContext *dc, const DeclContext *fromDC) {
856
846
// / nominal type.
857
847
DiagnosticBehavior SendableCheckContext::diagnosticBehavior (
858
848
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;
891
851
892
852
DiagnosticBehavior defaultBehavior = implicitSendableDiagnosticBehavior ();
893
853
@@ -902,6 +862,38 @@ DiagnosticBehavior SendableCheckContext::diagnosticBehavior(
902
862
return defaultBehavior;
903
863
}
904
864
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
+
905
897
static bool shouldDiagnosePreconcurrencyImports (SourceFile &sf) {
906
898
switch (sf.Kind ) {
907
899
case SourceFileKind::Interface:
@@ -2106,7 +2098,8 @@ namespace {
2106
2098
2107
2099
// / Note when the enclosing context could be put on a global actor.
2108
2100
// 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) {
2110
2103
// If we are in a synchronous function on the global actor,
2111
2104
// suggest annotating with the global actor itself.
2112
2105
if (auto fn = findAnnotatableFunction (dc)) {
@@ -2125,13 +2118,19 @@ namespace {
2125
2118
return false ;
2126
2119
2127
2120
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.
2128
2128
fn->diagnose (diag::add_globalactor_to_function,
2129
2129
globalActor->getWithoutParens ().getString (),
2130
2130
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 ;
2135
2134
}
2136
2135
}
2137
2136
}
@@ -2163,7 +2162,7 @@ namespace {
2163
2162
// Diagnose actor_isolated_non_self_reference as note
2164
2163
// if fix-it provided in missingGlobalActorOnContext
2165
2164
ctx.Diags .diagnose (error.loc , error.diag )
2166
- .limitBehavior (behavior);
2165
+ .limitBehaviorUntilSwiftVersion (behavior, 6 );
2167
2166
}
2168
2167
}
2169
2168
@@ -2188,7 +2187,7 @@ namespace {
2188
2187
// Diagnose actor_isolated_call as note if
2189
2188
// fix-it provided in missingGlobalActorOnContext
2190
2189
ctx.Diags .diagnose (error.loc , error.diag )
2191
- .limitBehavior (behavior);
2190
+ .limitBehaviorUntilSwiftVersion (behavior, 6 );
2192
2191
}
2193
2192
}
2194
2193
@@ -3012,12 +3011,21 @@ namespace {
3012
3011
import && import ->options .contains (ImportFlags::Preconcurrency);
3013
3012
const auto isPreconcurrencyUnspecifiedIsolation =
3014
3013
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
+
3015
3025
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);
3021
3029
value->diagnose (diag::kind_declared_here, value->getDescriptiveKind ());
3022
3030
if (const auto sourceFile = getDeclContext ()->getParentSourceFile ();
3023
3031
sourceFile && isPreconcurrencyImport) {
@@ -5248,7 +5256,7 @@ void swift::checkOverrideActorIsolation(ValueDecl *value) {
5248
5256
value->diagnose (
5249
5257
diag::actor_isolation_override_mismatch, isolation,
5250
5258
value, overriddenIsolation)
5251
- .limitBehavior (behavior);
5259
+ .limitBehaviorUntilSwiftVersion (behavior, 6 );
5252
5260
overridden->diagnose (diag::overridden_here);
5253
5261
}
5254
5262
@@ -5346,7 +5354,7 @@ static bool checkSendableInstanceStorage(
5346
5354
&& SendableCheckContext (dc, check)
5347
5355
.defaultDiagnosticBehavior () != DiagnosticBehavior::Ignore) {
5348
5356
sd->diagnose (diag::sendable_raw_storage, sd->getName ())
5349
- .limitBehavior (behavior);
5357
+ .limitBehaviorUntilSwiftVersion (behavior, 6 );
5350
5358
}
5351
5359
return true ;
5352
5360
}
@@ -5381,7 +5389,7 @@ static bool checkSendableInstanceStorage(
5381
5389
property
5382
5390
->diagnose (diag::concurrent_value_class_mutable_property,
5383
5391
property->getName (), nominal)
5384
- .limitBehavior (behavior);
5392
+ .limitBehaviorUntilSwiftVersion (behavior, 6 );
5385
5393
}
5386
5394
invalid = invalid || (behavior == DiagnosticBehavior::Unspecified);
5387
5395
return true ;
@@ -5393,10 +5401,13 @@ static bool checkSendableInstanceStorage(
5393
5401
}
5394
5402
5395
5403
// Check that the property type is Sendable.
5404
+ SendableCheckContext context (dc, check);
5396
5405
diagnoseNonSendableTypes (
5397
- propertyType, SendableCheckContext (dc, check) ,
5406
+ propertyType, context ,
5398
5407
/* inDerivedConformance*/ Type (), property->getLoc (),
5399
5408
[&](Type type, DiagnosticBehavior behavior) {
5409
+ auto preconcurrency =
5410
+ context.preconcurrencyBehavior (type->getAnyNominal ());
5400
5411
if (isImplicitSendableCheck (check)) {
5401
5412
// If this is for an externally-visible conformance, fail.
5402
5413
if (check == SendableCheck::ImplicitForExternallyVisible) {
@@ -5405,8 +5416,9 @@ static bool checkSendableInstanceStorage(
5405
5416
}
5406
5417
5407
5418
// 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 ;
5410
5422
5411
5423
invalid = true ;
5412
5424
return true ;
@@ -5415,7 +5427,8 @@ static bool checkSendableInstanceStorage(
5415
5427
property->diagnose (diag::non_concurrent_type_member,
5416
5428
propertyType, false , property->getName (),
5417
5429
nominal)
5418
- .limitBehavior (behavior);
5430
+ .limitBehaviorUntilSwiftVersion (behavior, 6 )
5431
+ .limitBehaviorIf (preconcurrency);
5419
5432
return false ;
5420
5433
});
5421
5434
@@ -5430,10 +5443,13 @@ static bool checkSendableInstanceStorage(
5430
5443
5431
5444
// / Handle an enum associated value.
5432
5445
bool operator ()(EnumElementDecl *element, Type elementType) override {
5446
+ SendableCheckContext context (dc, check);
5433
5447
diagnoseNonSendableTypes (
5434
- elementType, SendableCheckContext (dc, check) ,
5448
+ elementType, context ,
5435
5449
/* inDerivedConformance*/ Type (), element->getLoc (),
5436
5450
[&](Type type, DiagnosticBehavior behavior) {
5451
+ auto preconcurrency =
5452
+ context.preconcurrencyBehavior (elementType->getAnyNominal ());
5437
5453
if (isImplicitSendableCheck (check)) {
5438
5454
// If this is for an externally-visible conformance, fail.
5439
5455
if (check == SendableCheck::ImplicitForExternallyVisible) {
@@ -5442,7 +5458,8 @@ static bool checkSendableInstanceStorage(
5442
5458
}
5443
5459
5444
5460
// If we are to ignore this diagnostic, just continue.
5445
- if (behavior == DiagnosticBehavior::Ignore)
5461
+ if (behavior == DiagnosticBehavior::Ignore ||
5462
+ preconcurrency == DiagnosticBehavior::Ignore)
5446
5463
return false ;
5447
5464
5448
5465
invalid = true ;
@@ -5451,7 +5468,8 @@ static bool checkSendableInstanceStorage(
5451
5468
5452
5469
element->diagnose (diag::non_concurrent_type_member, type,
5453
5470
true , element->getName (), nominal)
5454
- .limitBehavior (behavior);
5471
+ .limitBehaviorUntilSwiftVersion (behavior, 6 )
5472
+ .limitBehaviorIf (preconcurrency);
5455
5473
return false ;
5456
5474
});
5457
5475
@@ -5510,7 +5528,7 @@ bool swift::checkSendableConformance(
5510
5528
nominal->getOutermostParentSourceFile ()) {
5511
5529
conformanceDecl->diagnose (diag::concurrent_value_outside_source_file,
5512
5530
nominal)
5513
- .limitBehavior (behavior);
5531
+ .limitBehaviorUntilSwiftVersion (behavior, 6 );
5514
5532
5515
5533
if (behavior == DiagnosticBehavior::Unspecified)
5516
5534
return true ;
@@ -5523,7 +5541,7 @@ bool swift::checkSendableConformance(
5523
5541
if (!classDecl->isSemanticallyFinal ()) {
5524
5542
classDecl->diagnose (diag::concurrent_value_nonfinal_class,
5525
5543
classDecl->getName ())
5526
- .limitBehavior (behavior);
5544
+ .limitBehaviorUntilSwiftVersion (behavior, 6 );
5527
5545
5528
5546
if (behavior == DiagnosticBehavior::Unspecified)
5529
5547
return true ;
@@ -5538,7 +5556,7 @@ bool swift::checkSendableConformance(
5538
5556
->diagnose (diag::concurrent_value_inherit,
5539
5557
nominal->getASTContext ().LangOpts .EnableObjCInterop ,
5540
5558
classDecl->getName ())
5541
- .limitBehavior (behavior);
5559
+ .limitBehaviorUntilSwiftVersion (behavior, 6 );
5542
5560
5543
5561
if (behavior == DiagnosticBehavior::Unspecified)
5544
5562
return true ;
0 commit comments