@@ -601,46 +601,96 @@ static bool hasUnavailableConformance(ProtocolConformanceRef conformance) {
601601 return false ;
602602}
603603
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+
604678// / Produce a diagnostic for a single instance of a non-Sendable type where
605679// / a Sendable type is required.
606680static bool diagnoseSingleNonSendableType (
607- Type type, ModuleDecl * module , SourceLoc loc,
681+ Type type, SendableCheckContext fromContext , SourceLoc loc,
608682 llvm::function_ref<
609683 std::pair<DiagnosticBehavior, bool >(Type, DiagnosticBehavior)> diagnose) {
610684
611685 auto behavior = DiagnosticBehavior::Unspecified;
612686
687+ auto module = fromContext.fromDC ->getParentModule ();
613688 ASTContext &ctx = module ->getASTContext ();
614689 auto nominal = type->getAnyNominal ();
615- const LangOptions &langOpts = ctx.LangOpts ;
616690 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 ();
644694 }
645695
646696 DiagnosticBehavior actualBehavior;
@@ -667,9 +717,11 @@ static bool diagnoseSingleNonSendableType(
667717}
668718
669719bool swift::diagnoseNonSendableTypes (
670- Type type, ModuleDecl * module , SourceLoc loc,
720+ Type type, SendableCheckContext fromContext , SourceLoc loc,
671721 llvm::function_ref<
672722 std::pair<DiagnosticBehavior, bool >(Type, DiagnosticBehavior)> diagnose) {
723+ auto module = fromContext.fromDC ->getParentModule ();
724+
673725 // If the Sendable protocol is missing, do nothing.
674726 auto proto = module ->getASTContext ().getProtocol (KnownProtocolKind::Sendable);
675727 if (!proto)
@@ -678,15 +730,15 @@ bool swift::diagnoseNonSendableTypes(
678730 // FIXME: More detail for unavailable conformances.
679731 auto conformance = TypeChecker::conformsToProtocol (type, proto, module );
680732 if (conformance.isInvalid () || hasUnavailableConformance (conformance)) {
681- return diagnoseSingleNonSendableType (type, module , loc, diagnose);
733+ return diagnoseSingleNonSendableType (type, fromContext , loc, diagnose);
682734 }
683735
684736 // Walk the conformance, diagnosing any missing Sendable conformances.
685737 bool anyMissing = false ;
686738 conformance.forEachMissingConformance (module ,
687739 [&](BuiltinProtocolConformance *missing) {
688740 if (diagnoseSingleNonSendableType (
689- missing->getType (), module , loc, diagnose)) {
741+ missing->getType (), fromContext , loc, diagnose)) {
690742 anyMissing = true ;
691743 }
692744
@@ -697,23 +749,23 @@ bool swift::diagnoseNonSendableTypes(
697749}
698750
699751bool swift::diagnoseNonSendableTypesInReference (
700- ConcreteDeclRef declRef, ModuleDecl * module , SourceLoc loc,
752+ ConcreteDeclRef declRef, const DeclContext *fromDC , SourceLoc loc,
701753 ConcurrentReferenceKind refKind) {
702754 // For functions, check the parameter and result types.
703755 SubstitutionMap subs = declRef.getSubstitutions ();
704756 if (auto function = dyn_cast<AbstractFunctionDecl>(declRef.getDecl ())) {
705757 for (auto param : *function->getParameters ()) {
706758 Type paramType = param->getInterfaceType ().subst (subs);
707759 if (diagnoseNonSendableTypes (
708- paramType, module , loc, diag::non_sendable_param_type))
760+ paramType, fromDC , loc, diag::non_sendable_param_type))
709761 return true ;
710762 }
711763
712764 // Check the result type of a function.
713765 if (auto func = dyn_cast<FuncDecl>(function)) {
714766 Type resultType = func->getResultInterfaceType ().subst (subs);
715767 if (diagnoseNonSendableTypes (
716- resultType, module , loc, diag::non_sendable_result_type))
768+ resultType, fromDC , loc, diag::non_sendable_result_type))
717769 return true ;
718770 }
719771
@@ -725,7 +777,7 @@ bool swift::diagnoseNonSendableTypesInReference(
725777 ? var->getType ()
726778 : var->getValueInterfaceType ().subst (subs);
727779 if (diagnoseNonSendableTypes (
728- propertyType, module , loc,
780+ propertyType, fromDC , loc,
729781 diag::non_sendable_property_type,
730782 var->getDescriptiveKind (), var->getName (),
731783 var->isLocalCapture ()))
@@ -736,14 +788,14 @@ bool swift::diagnoseNonSendableTypesInReference(
736788 for (auto param : *subscript->getIndices ()) {
737789 Type paramType = param->getInterfaceType ().subst (subs);
738790 if (diagnoseNonSendableTypes (
739- paramType, module , loc, diag::non_sendable_param_type))
791+ paramType, fromDC , loc, diag::non_sendable_param_type))
740792 return true ;
741793 }
742794
743795 // Check the element type of a subscript.
744796 Type resultType = subscript->getElementInterfaceType ().subst (subs);
745797 if (diagnoseNonSendableTypes (
746- resultType, module , loc, diag::non_sendable_result_type))
798+ resultType, fromDC , loc, diag::non_sendable_result_type))
747799 return true ;
748800
749801 return false ;
@@ -753,9 +805,9 @@ bool swift::diagnoseNonSendableTypesInReference(
753805}
754806
755807void swift::diagnoseMissingSendableConformance (
756- SourceLoc loc, Type type, ModuleDecl * module ) {
808+ SourceLoc loc, Type type, const DeclContext *fromDC ) {
757809 diagnoseNonSendableTypes (
758- type, module , loc, diag::non_sendable_type);
810+ type, fromDC , loc, diag::non_sendable_type);
759811}
760812
761813namespace {
@@ -1893,7 +1945,7 @@ namespace {
18931945 // Check for non-sendable types.
18941946 bool problemFound =
18951947 diagnoseNonSendableTypesInReference (
1896- concDeclRef, getDeclContext ()-> getParentModule () , declLoc,
1948+ concDeclRef, getDeclContext (), declLoc,
18971949 ConcurrentReferenceKind::SynchronousAsAsyncCall);
18981950 if (problemFound)
18991951 result = AsyncMarkingResult::NotSendable;
@@ -2023,14 +2075,14 @@ namespace {
20232075 for (const auto ¶m : fnType->getParams ()) {
20242076 // FIXME: Dig out the locations of the corresponding arguments.
20252077 if (diagnoseNonSendableTypes (
2026- param.getParameterType (), getParentModule (), apply->getLoc (),
2078+ param.getParameterType (), getDeclContext (), apply->getLoc (),
20272079 diag::non_sendable_param_type))
20282080 return true ;
20292081 }
20302082
20312083 // Check for sendability of the result type.
20322084 if (diagnoseNonSendableTypes (
2033- fnType->getResult (), getParentModule (), apply->getLoc (),
2085+ fnType->getResult (), getDeclContext (), apply->getLoc (),
20342086 diag::non_sendable_result_type))
20352087 return true ;
20362088
@@ -2056,7 +2108,7 @@ namespace {
20562108 // A cross-actor access requires types to be concurrent-safe.
20572109 if (isCrossActor) {
20582110 return diagnoseNonSendableTypesInReference (
2059- valueRef, getParentModule (), loc,
2111+ valueRef, getDeclContext (), loc,
20602112 ConcurrentReferenceKind::CrossActor);
20612113 }
20622114
@@ -2174,7 +2226,7 @@ namespace {
21742226 (ctx.LangOpts .EnableExperimentalFlowSensitiveConcurrentCaptures &&
21752227 parent.dyn_cast <LoadExpr *>())) {
21762228 return diagnoseNonSendableTypesInReference (
2177- valueRef, getParentModule (), loc,
2229+ valueRef, getDeclContext (), loc,
21782230 ConcurrentReferenceKind::LocalCapture);
21792231 }
21802232
@@ -2226,7 +2278,7 @@ namespace {
22262278 auto type = component.getComponentType ();
22272279 if (shouldDiagnoseExistingDataRaces (getDeclContext ()) &&
22282280 diagnoseNonSendableTypes (
2229- type, getParentModule (), component.getLoc (),
2281+ type, getDeclContext (), component.getLoc (),
22302282 diag::non_sendable_keypath_access))
22312283 return true ;
22322284
@@ -2293,7 +2345,7 @@ namespace {
22932345 if (type &&
22942346 shouldDiagnoseExistingDataRaces (getDeclContext ()) &&
22952347 diagnoseNonSendableTypes (
2296- type, getParentModule (), component.getLoc (),
2348+ type, getDeclContext (), component.getLoc (),
22972349 diag::non_sendable_keypath_capture))
22982350 diagnosed = true ;
22992351 }
@@ -2399,7 +2451,7 @@ namespace {
23992451 }
24002452
24012453 return diagnoseNonSendableTypesInReference (
2402- memberRef, getDeclContext ()-> getParentModule () , memberLoc,
2454+ memberRef, getDeclContext (), memberLoc,
24032455 ConcurrentReferenceKind::CrossActor);
24042456 }
24052457
@@ -3172,9 +3224,8 @@ ActorIsolation ActorIsolationRequest::evaluate(
31723224 subs = genericEnv->getForwardingSubstitutionMap ();
31733225 }
31743226 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);
31783229 }
31793230
31803231 // Classes with global actors have additional rules regarding inheritance.
@@ -3589,13 +3640,6 @@ bool swift::contextUsesConcurrencyFeatures(const DeclContext *dc) {
35893640 return false ;
35903641}
35913642
3592- static bool shouldDiagnoseExistingDataRaces (const DeclContext *dc) {
3593- if (dc->getParentModule ()->isConcurrencyChecked ())
3594- return true ;
3595-
3596- return contextUsesConcurrencyFeatures (dc);
3597- }
3598-
35993643// / Limit the diagnostic behavior used when performing checks for the Sendable
36003644// / instance storage of Sendable types.
36013645// /
@@ -3718,7 +3762,7 @@ static bool checkSendableInstanceStorage(
37183762
37193763 // Check that the property type is Sendable.
37203764 bool diagnosedProperty = diagnoseNonSendableTypes (
3721- propertyType, dc-> getParentModule ( ), property->getLoc (),
3765+ propertyType, SendableCheckContext (dc, check ), property->getLoc (),
37223766 [&](Type type, DiagnosticBehavior suggestedBehavior) {
37233767 auto action = limitSendableInstanceBehavior (
37243768 langOpts, check, suggestedBehavior);
@@ -3748,7 +3792,7 @@ static bool checkSendableInstanceStorage(
37483792 // / Handle an enum associated value.
37493793 bool operator ()(EnumElementDecl *element, Type elementType) {
37503794 bool diagnosedElement = diagnoseNonSendableTypes (
3751- elementType, dc-> getParentModule ( ), element->getLoc (),
3795+ elementType, SendableCheckContext (dc, check ), element->getLoc (),
37523796 [&](Type type, DiagnosticBehavior suggestedBehavior) {
37533797 auto action = limitSendableInstanceBehavior (
37543798 langOpts, check, suggestedBehavior);
0 commit comments