@@ -601,46 +601,96 @@ static bool hasUnavailableConformance(ProtocolConformanceRef conformance) {
601
601
return false ;
602
602
}
603
603
604
+ static bool shouldDiagnoseExistingDataRaces (const DeclContext *dc) {
605
+ if (dc->getParentModule ()->isConcurrencyChecked ())
606
+ return true ;
607
+
608
+ return contextUsesConcurrencyFeatures (dc);
609
+ }
610
+
611
+ // / Determine the default diagnostic behavior for this language mode.
612
+ static DiagnosticBehavior defaultSendableDiagnosticBehavior (
613
+ const LangOptions &langOpts) {
614
+ // Prior to Swift 6, all Sendable-related diagnostics are warnings.
615
+ if (!langOpts.isSwiftVersionAtLeast (6 ))
616
+ return DiagnosticBehavior::Warning;
617
+
618
+ return DiagnosticBehavior::Unspecified;
619
+ }
620
+
621
+ DiagnosticBehavior SendableCheckContext::defaultDiagnosticBehavior () const {
622
+ // If we're not supposed to diagnose existing data races from this context,
623
+ // ignore the diagnostic entirely.
624
+ if (!shouldDiagnoseExistingDataRaces (fromDC))
625
+ return DiagnosticBehavior::Ignore;
626
+
627
+ return defaultSendableDiagnosticBehavior (fromDC->getASTContext ().LangOpts );
628
+ }
629
+
630
+ // / Determine the diagnostic behavior for a Sendable reference to the given
631
+ // / nominal type.
632
+ DiagnosticBehavior SendableCheckContext::diagnosticBehavior (
633
+ NominalTypeDecl *nominal) const {
634
+ // Determine whether the type was explicitly non-Sendable.
635
+ auto nominalModule = nominal->getParentModule ();
636
+ bool isExplicitlyNonSendable = nominalModule->isConcurrencyChecked ();
637
+
638
+ // If we are performing an explicit conformance check, always consider this
639
+ // to be an explicitly non-Sendable type.
640
+ if (conformanceCheck) {
641
+ switch (*conformanceCheck) {
642
+ case SendableCheck::Explicit:
643
+ isExplicitlyNonSendable = true ;
644
+ break ;
645
+
646
+ case SendableCheck::ImpliedByStandardProtocol:
647
+ case SendableCheck::Implicit:
648
+ break ;
649
+ }
650
+ }
651
+
652
+ // Determine whether this nominal type is visible via a @_predatesConcurrency
653
+ // import.
654
+ ImportDecl *predatesConcurrencyImport = nullptr ;
655
+
656
+ // When the type is explicitly non-Sendable...
657
+ if (isExplicitlyNonSendable) {
658
+ // @_predatesConcurrency imports downgrade the diagnostic to a warning.
659
+ if (predatesConcurrencyImport) {
660
+ // FIXME: Note that this @_predatesConcurrency import was "used".
661
+ return DiagnosticBehavior::Warning;
662
+ }
663
+
664
+ return defaultSendableDiagnosticBehavior (fromDC->getASTContext ().LangOpts );
665
+ }
666
+
667
+ // When the type is implicitly non-Sendable...
668
+
669
+ // @_predatesConcurrency always suppresses the diagnostic.
670
+ if (predatesConcurrencyImport) {
671
+ // FIXME: Note that this @_predatesConcurrency import was "used".
672
+ return DiagnosticBehavior::Ignore;
673
+ }
674
+
675
+ return defaultDiagnosticBehavior ();
676
+ }
677
+
604
678
// / Produce a diagnostic for a single instance of a non-Sendable type where
605
679
// / a Sendable type is required.
606
680
static bool diagnoseSingleNonSendableType (
607
- Type type, ModuleDecl * module , SourceLoc loc,
681
+ Type type, SendableCheckContext fromContext , SourceLoc loc,
608
682
llvm::function_ref<
609
683
std::pair<DiagnosticBehavior, bool >(Type, DiagnosticBehavior)> diagnose) {
610
684
611
685
auto behavior = DiagnosticBehavior::Unspecified;
612
686
687
+ auto module = fromContext.fromDC ->getParentModule ();
613
688
ASTContext &ctx = module ->getASTContext ();
614
689
auto nominal = type->getAnyNominal ();
615
- const LangOptions &langOpts = ctx.LangOpts ;
616
690
if (nominal) {
617
- // A nominal type that has not provided conformance to Sendable will be
618
- // diagnosed based on whether its defining module was consistently
619
- // checked for concurrency.
620
- auto nominalModule = nominal->getParentModule ();
621
-
622
- if (langOpts.isSwiftVersionAtLeast (6 )) {
623
- // In Swift 6, error when the nominal type comes from a module that
624
- // had the concurrency checks consistently applied or from this module.
625
- // Otherwise, warn.
626
- if (nominalModule->isConcurrencyChecked () || nominalModule == module )
627
- behavior = DiagnosticBehavior::Unspecified;
628
- else
629
- behavior = DiagnosticBehavior::Warning;
630
- } else {
631
- // In Swift 5, warn if either the imported or importing model is
632
- // checking for concurrency, or if the nominal type comes from this
633
- // module. Otherwise, leave a safety hole.
634
- if (nominalModule->isConcurrencyChecked () ||
635
- nominalModule == module ||
636
- langOpts.WarnConcurrency )
637
- behavior = DiagnosticBehavior::Warning;
638
- else
639
- behavior = DiagnosticBehavior::Ignore;
640
- }
641
- } else if (!langOpts.isSwiftVersionAtLeast (6 )) {
642
- // Always warn in Swift 5.
643
- behavior = DiagnosticBehavior::Warning;
691
+ behavior = fromContext.diagnosticBehavior (nominal);
692
+ } else {
693
+ behavior = fromContext.defaultDiagnosticBehavior ();
644
694
}
645
695
646
696
DiagnosticBehavior actualBehavior;
@@ -667,9 +717,11 @@ static bool diagnoseSingleNonSendableType(
667
717
}
668
718
669
719
bool swift::diagnoseNonSendableTypes (
670
- Type type, ModuleDecl * module , SourceLoc loc,
720
+ Type type, SendableCheckContext fromContext , SourceLoc loc,
671
721
llvm::function_ref<
672
722
std::pair<DiagnosticBehavior, bool >(Type, DiagnosticBehavior)> diagnose) {
723
+ auto module = fromContext.fromDC ->getParentModule ();
724
+
673
725
// If the Sendable protocol is missing, do nothing.
674
726
auto proto = module ->getASTContext ().getProtocol (KnownProtocolKind::Sendable);
675
727
if (!proto)
@@ -678,15 +730,15 @@ bool swift::diagnoseNonSendableTypes(
678
730
// FIXME: More detail for unavailable conformances.
679
731
auto conformance = TypeChecker::conformsToProtocol (type, proto, module );
680
732
if (conformance.isInvalid () || hasUnavailableConformance (conformance)) {
681
- return diagnoseSingleNonSendableType (type, module , loc, diagnose);
733
+ return diagnoseSingleNonSendableType (type, fromContext , loc, diagnose);
682
734
}
683
735
684
736
// Walk the conformance, diagnosing any missing Sendable conformances.
685
737
bool anyMissing = false ;
686
738
conformance.forEachMissingConformance (module ,
687
739
[&](BuiltinProtocolConformance *missing) {
688
740
if (diagnoseSingleNonSendableType (
689
- missing->getType (), module , loc, diagnose)) {
741
+ missing->getType (), fromContext , loc, diagnose)) {
690
742
anyMissing = true ;
691
743
}
692
744
@@ -697,23 +749,23 @@ bool swift::diagnoseNonSendableTypes(
697
749
}
698
750
699
751
bool swift::diagnoseNonSendableTypesInReference (
700
- ConcreteDeclRef declRef, ModuleDecl * module , SourceLoc loc,
752
+ ConcreteDeclRef declRef, const DeclContext *fromDC , SourceLoc loc,
701
753
ConcurrentReferenceKind refKind) {
702
754
// For functions, check the parameter and result types.
703
755
SubstitutionMap subs = declRef.getSubstitutions ();
704
756
if (auto function = dyn_cast<AbstractFunctionDecl>(declRef.getDecl ())) {
705
757
for (auto param : *function->getParameters ()) {
706
758
Type paramType = param->getInterfaceType ().subst (subs);
707
759
if (diagnoseNonSendableTypes (
708
- paramType, module , loc, diag::non_sendable_param_type))
760
+ paramType, fromDC , loc, diag::non_sendable_param_type))
709
761
return true ;
710
762
}
711
763
712
764
// Check the result type of a function.
713
765
if (auto func = dyn_cast<FuncDecl>(function)) {
714
766
Type resultType = func->getResultInterfaceType ().subst (subs);
715
767
if (diagnoseNonSendableTypes (
716
- resultType, module , loc, diag::non_sendable_result_type))
768
+ resultType, fromDC , loc, diag::non_sendable_result_type))
717
769
return true ;
718
770
}
719
771
@@ -725,7 +777,7 @@ bool swift::diagnoseNonSendableTypesInReference(
725
777
? var->getType ()
726
778
: var->getValueInterfaceType ().subst (subs);
727
779
if (diagnoseNonSendableTypes (
728
- propertyType, module , loc,
780
+ propertyType, fromDC , loc,
729
781
diag::non_sendable_property_type,
730
782
var->getDescriptiveKind (), var->getName (),
731
783
var->isLocalCapture ()))
@@ -736,14 +788,14 @@ bool swift::diagnoseNonSendableTypesInReference(
736
788
for (auto param : *subscript->getIndices ()) {
737
789
Type paramType = param->getInterfaceType ().subst (subs);
738
790
if (diagnoseNonSendableTypes (
739
- paramType, module , loc, diag::non_sendable_param_type))
791
+ paramType, fromDC , loc, diag::non_sendable_param_type))
740
792
return true ;
741
793
}
742
794
743
795
// Check the element type of a subscript.
744
796
Type resultType = subscript->getElementInterfaceType ().subst (subs);
745
797
if (diagnoseNonSendableTypes (
746
- resultType, module , loc, diag::non_sendable_result_type))
798
+ resultType, fromDC , loc, diag::non_sendable_result_type))
747
799
return true ;
748
800
749
801
return false ;
@@ -753,9 +805,9 @@ bool swift::diagnoseNonSendableTypesInReference(
753
805
}
754
806
755
807
void swift::diagnoseMissingSendableConformance (
756
- SourceLoc loc, Type type, ModuleDecl * module ) {
808
+ SourceLoc loc, Type type, const DeclContext *fromDC ) {
757
809
diagnoseNonSendableTypes (
758
- type, module , loc, diag::non_sendable_type);
810
+ type, fromDC , loc, diag::non_sendable_type);
759
811
}
760
812
761
813
namespace {
@@ -1893,7 +1945,7 @@ namespace {
1893
1945
// Check for non-sendable types.
1894
1946
bool problemFound =
1895
1947
diagnoseNonSendableTypesInReference (
1896
- concDeclRef, getDeclContext ()-> getParentModule () , declLoc,
1948
+ concDeclRef, getDeclContext (), declLoc,
1897
1949
ConcurrentReferenceKind::SynchronousAsAsyncCall);
1898
1950
if (problemFound)
1899
1951
result = AsyncMarkingResult::NotSendable;
@@ -2023,14 +2075,14 @@ namespace {
2023
2075
for (const auto ¶m : fnType->getParams ()) {
2024
2076
// FIXME: Dig out the locations of the corresponding arguments.
2025
2077
if (diagnoseNonSendableTypes (
2026
- param.getParameterType (), getParentModule (), apply->getLoc (),
2078
+ param.getParameterType (), getDeclContext (), apply->getLoc (),
2027
2079
diag::non_sendable_param_type))
2028
2080
return true ;
2029
2081
}
2030
2082
2031
2083
// Check for sendability of the result type.
2032
2084
if (diagnoseNonSendableTypes (
2033
- fnType->getResult (), getParentModule (), apply->getLoc (),
2085
+ fnType->getResult (), getDeclContext (), apply->getLoc (),
2034
2086
diag::non_sendable_result_type))
2035
2087
return true ;
2036
2088
@@ -2056,7 +2108,7 @@ namespace {
2056
2108
// A cross-actor access requires types to be concurrent-safe.
2057
2109
if (isCrossActor) {
2058
2110
return diagnoseNonSendableTypesInReference (
2059
- valueRef, getParentModule (), loc,
2111
+ valueRef, getDeclContext (), loc,
2060
2112
ConcurrentReferenceKind::CrossActor);
2061
2113
}
2062
2114
@@ -2174,7 +2226,7 @@ namespace {
2174
2226
(ctx.LangOpts .EnableExperimentalFlowSensitiveConcurrentCaptures &&
2175
2227
parent.dyn_cast <LoadExpr *>())) {
2176
2228
return diagnoseNonSendableTypesInReference (
2177
- valueRef, getParentModule (), loc,
2229
+ valueRef, getDeclContext (), loc,
2178
2230
ConcurrentReferenceKind::LocalCapture);
2179
2231
}
2180
2232
@@ -2226,7 +2278,7 @@ namespace {
2226
2278
auto type = component.getComponentType ();
2227
2279
if (shouldDiagnoseExistingDataRaces (getDeclContext ()) &&
2228
2280
diagnoseNonSendableTypes (
2229
- type, getParentModule (), component.getLoc (),
2281
+ type, getDeclContext (), component.getLoc (),
2230
2282
diag::non_sendable_keypath_access))
2231
2283
return true ;
2232
2284
@@ -2293,7 +2345,7 @@ namespace {
2293
2345
if (type &&
2294
2346
shouldDiagnoseExistingDataRaces (getDeclContext ()) &&
2295
2347
diagnoseNonSendableTypes (
2296
- type, getParentModule (), component.getLoc (),
2348
+ type, getDeclContext (), component.getLoc (),
2297
2349
diag::non_sendable_keypath_capture))
2298
2350
diagnosed = true ;
2299
2351
}
@@ -2399,7 +2451,7 @@ namespace {
2399
2451
}
2400
2452
2401
2453
return diagnoseNonSendableTypesInReference (
2402
- memberRef, getDeclContext ()-> getParentModule () , memberLoc,
2454
+ memberRef, getDeclContext (), memberLoc,
2403
2455
ConcurrentReferenceKind::CrossActor);
2404
2456
}
2405
2457
@@ -3172,9 +3224,8 @@ ActorIsolation ActorIsolationRequest::evaluate(
3172
3224
subs = genericEnv->getForwardingSubstitutionMap ();
3173
3225
}
3174
3226
diagnoseNonSendableTypesInReference (
3175
- ConcreteDeclRef (value, subs),
3176
- value->getDeclContext ()->getParentModule (), value->getLoc (),
3177
- ConcurrentReferenceKind::Nonisolated);
3227
+ ConcreteDeclRef (value, subs), value->getDeclContext (),
3228
+ value->getLoc (), ConcurrentReferenceKind::Nonisolated);
3178
3229
}
3179
3230
3180
3231
// Classes with global actors have additional rules regarding inheritance.
@@ -3589,13 +3640,6 @@ bool swift::contextUsesConcurrencyFeatures(const DeclContext *dc) {
3589
3640
return false ;
3590
3641
}
3591
3642
3592
- static bool shouldDiagnoseExistingDataRaces (const DeclContext *dc) {
3593
- if (dc->getParentModule ()->isConcurrencyChecked ())
3594
- return true ;
3595
-
3596
- return contextUsesConcurrencyFeatures (dc);
3597
- }
3598
-
3599
3643
// / Limit the diagnostic behavior used when performing checks for the Sendable
3600
3644
// / instance storage of Sendable types.
3601
3645
// /
@@ -3718,7 +3762,7 @@ static bool checkSendableInstanceStorage(
3718
3762
3719
3763
// Check that the property type is Sendable.
3720
3764
bool diagnosedProperty = diagnoseNonSendableTypes (
3721
- propertyType, dc-> getParentModule ( ), property->getLoc (),
3765
+ propertyType, SendableCheckContext (dc, check ), property->getLoc (),
3722
3766
[&](Type type, DiagnosticBehavior suggestedBehavior) {
3723
3767
auto action = limitSendableInstanceBehavior (
3724
3768
langOpts, check, suggestedBehavior);
@@ -3748,7 +3792,7 @@ static bool checkSendableInstanceStorage(
3748
3792
// / Handle an enum associated value.
3749
3793
bool operator ()(EnumElementDecl *element, Type elementType) {
3750
3794
bool diagnosedElement = diagnoseNonSendableTypes (
3751
- elementType, dc-> getParentModule ( ), element->getLoc (),
3795
+ elementType, SendableCheckContext (dc, check ), element->getLoc (),
3752
3796
[&](Type type, DiagnosticBehavior suggestedBehavior) {
3753
3797
auto action = limitSendableInstanceBehavior (
3754
3798
langOpts, check, suggestedBehavior);
0 commit comments