@@ -798,7 +798,7 @@ bool SendableCheckContext::warnInMinimalChecking() const {
798798 case SendableCheck::Explicit:
799799 return true ;
800800
801- case SendableCheck::ImpliedByStandardProtocol :
801+ case SendableCheck::ImpliedByPreconcurrencyProtocol :
802802 case SendableCheck::Implicit:
803803 case SendableCheck::ImplicitForExternallyVisible:
804804 return false ;
@@ -6768,11 +6768,16 @@ static bool checkSendableInstanceStorage(
67686768 if (property->supportsMutation () && isolation.isUnspecified ()) {
67696769 auto behavior =
67706770 SendableCheckContext (dc, check).defaultDiagnosticBehavior ();
6771+ // If Sendable came from a `@preconcurrency` protocol the error
6772+ // should be downgraded even with strict concurrency checking to
6773+ // allow clients time to address the new requirement.
6774+ auto preconcurrency =
6775+ check == SendableCheck::ImpliedByPreconcurrencyProtocol;
67716776 if (behavior != DiagnosticBehavior::Ignore) {
67726777 property
67736778 ->diagnose (diag::concurrent_value_class_mutable_property,
67746779 property->getName (), nominal)
6775- .limitBehaviorUntilSwiftVersion (behavior, 6 );
6780+ .limitBehaviorWithPreconcurrency (behavior, preconcurrency );
67766781 }
67776782 invalid = invalid || (behavior == DiagnosticBehavior::Unspecified);
67786783 return true ;
@@ -6783,57 +6788,22 @@ static bool checkSendableInstanceStorage(
67836788 }
67846789 }
67856790
6786- // Check that the property type is Sendable.
6787- SendableCheckContext context (dc, check);
6788- diagnoseNonSendableTypes (
6789- propertyType, context,
6790- /* inDerivedConformance*/ Type (), property->getLoc (),
6791- [&](Type type, DiagnosticBehavior behavior) {
6792- auto preconcurrency = context.preconcurrencyBehavior (type);
6793- if (isImplicitSendableCheck (check)) {
6794- // If this is for an externally-visible conformance, fail.
6795- if (check == SendableCheck::ImplicitForExternallyVisible) {
6796- invalid = true ;
6797- return true ;
6798- }
6799-
6800- // If we are to ignore this diagnostic, just continue.
6801- if (behavior == DiagnosticBehavior::Ignore ||
6802- preconcurrency == DiagnosticBehavior::Ignore)
6803- return true ;
6804-
6805- invalid = true ;
6806- return true ;
6807- }
6808-
6809- if (preconcurrency)
6810- behavior = preconcurrency.value ();
6811-
6812- property
6813- ->diagnose (diag::non_concurrent_type_member, propertyType,
6814- false , property->getName (), nominal)
6815- .limitBehaviorWithPreconcurrency (behavior,
6816- preconcurrency.has_value ());
6817- return false ;
6818- });
6819-
6820- if (invalid) {
6821- // For implicit checks, bail out early if anything failed.
6822- if (isImplicitSendableCheck (check))
6823- return true ;
6824- }
6825-
6826- return false ;
6791+ return checkSendabilityOfMemberType (property, propertyType);
68276792 }
68286793
68296794 // / Handle an enum associated value.
68306795 bool operator ()(EnumElementDecl *element, Type elementType) override {
6831- SendableCheckContext context (dc, check);
6796+ return checkSendabilityOfMemberType (element, elementType);
6797+ }
6798+
6799+ private:
6800+ bool checkSendabilityOfMemberType (ValueDecl *member, Type memberType) {
6801+ SendableCheckContext context (dc, check);
68326802 diagnoseNonSendableTypes (
6833- elementType , context,
6834- /* inDerivedConformance*/ Type (), element ->getLoc (),
6803+ memberType , context,
6804+ /* inDerivedConformance*/ Type (), member ->getLoc (),
68356805 [&](Type type, DiagnosticBehavior behavior) {
6836- auto preconcurrency = context.preconcurrencyBehavior (type);
6806+ auto preconcurrencyBehavior = context.preconcurrencyBehavior (type);
68376807 if (isImplicitSendableCheck (check)) {
68386808 // If this is for an externally-visible conformance, fail.
68396809 if (check == SendableCheck::ImplicitForExternallyVisible) {
@@ -6843,21 +6813,29 @@ static bool checkSendableInstanceStorage(
68436813
68446814 // If we are to ignore this diagnostic, just continue.
68456815 if (behavior == DiagnosticBehavior::Ignore ||
6846- preconcurrency == DiagnosticBehavior::Ignore)
6816+ preconcurrencyBehavior == DiagnosticBehavior::Ignore)
68476817 return true ;
68486818
68496819 invalid = true ;
68506820 return true ;
68516821 }
68526822
6853- if (preconcurrency)
6854- behavior = preconcurrency.value ();
6855-
6856- element
6857- ->diagnose (diag::non_concurrent_type_member, type, true ,
6858- element->getName (), nominal)
6859- .limitBehaviorWithPreconcurrency (behavior,
6860- preconcurrency.has_value ());
6823+ // If Sendable came from a `@preconcurrency` protocol the error
6824+ // should be downgraded even with strict concurrency checking to
6825+ // allow clients time to address the new requirement.
6826+ bool fromPreconcurrencyConformance =
6827+ check == SendableCheck::ImpliedByPreconcurrencyProtocol;
6828+
6829+ if (preconcurrencyBehavior)
6830+ behavior = preconcurrencyBehavior.value ();
6831+
6832+ member
6833+ ->diagnose (diag::non_concurrent_type_member, type,
6834+ isa<EnumElementDecl>(member), member->getName (),
6835+ nominal, type->isEqual (memberType))
6836+ .limitBehaviorWithPreconcurrency (
6837+ behavior, fromPreconcurrencyConformance ||
6838+ preconcurrencyBehavior.has_value ());
68616839 return false ;
68626840 });
68636841
@@ -6869,6 +6847,7 @@ static bool checkSendableInstanceStorage(
68696847
68706848 return false ;
68716849 }
6850+
68726851 } visitor(nominal, dc, check);
68736852
68746853 return visitor.visit(nominal, dc) || visitor.invalid;
0 commit comments