@@ -797,7 +797,7 @@ bool SendableCheckContext::warnInMinimalChecking() const {
797797 case SendableCheck::Explicit:
798798 return true ;
799799
800- case SendableCheck::ImpliedByStandardProtocol :
800+ case SendableCheck::ImpliedByPreconcurrencyProtocol :
801801 case SendableCheck::Implicit:
802802 case SendableCheck::ImplicitForExternallyVisible:
803803 return false ;
@@ -6748,11 +6748,16 @@ static bool checkSendableInstanceStorage(
67486748 if (property->supportsMutation () && isolation.isUnspecified ()) {
67496749 auto behavior =
67506750 SendableCheckContext (dc, check).defaultDiagnosticBehavior ();
6751+ // If Sendable came from a `@preconcurrency` protocol the error
6752+ // should be downgraded even with strict concurrency checking to
6753+ // allow clients time to address the new requirement.
6754+ auto preconcurrency =
6755+ check == SendableCheck::ImpliedByPreconcurrencyProtocol;
67516756 if (behavior != DiagnosticBehavior::Ignore) {
67526757 property
67536758 ->diagnose (diag::concurrent_value_class_mutable_property,
67546759 property->getName (), nominal)
6755- .limitBehaviorUntilSwiftVersion (behavior, 6 );
6760+ .limitBehaviorWithPreconcurrency (behavior, preconcurrency );
67566761 }
67576762 invalid = invalid || (behavior == DiagnosticBehavior::Unspecified);
67586763 return true ;
@@ -6763,57 +6768,22 @@ static bool checkSendableInstanceStorage(
67636768 }
67646769 }
67656770
6766- // Check that the property type is Sendable.
6767- SendableCheckContext context (dc, check);
6768- diagnoseNonSendableTypes (
6769- propertyType, context,
6770- /* inDerivedConformance*/ Type (), property->getLoc (),
6771- [&](Type type, DiagnosticBehavior behavior) {
6772- auto preconcurrency = context.preconcurrencyBehavior (type);
6773- if (isImplicitSendableCheck (check)) {
6774- // If this is for an externally-visible conformance, fail.
6775- if (check == SendableCheck::ImplicitForExternallyVisible) {
6776- invalid = true ;
6777- return true ;
6778- }
6779-
6780- // If we are to ignore this diagnostic, just continue.
6781- if (behavior == DiagnosticBehavior::Ignore ||
6782- preconcurrency == DiagnosticBehavior::Ignore)
6783- return true ;
6784-
6785- invalid = true ;
6786- return true ;
6787- }
6788-
6789- if (preconcurrency)
6790- behavior = preconcurrency.value ();
6791-
6792- property
6793- ->diagnose (diag::non_concurrent_type_member, propertyType,
6794- false , property->getName (), nominal)
6795- .limitBehaviorWithPreconcurrency (behavior,
6796- preconcurrency.has_value ());
6797- return false ;
6798- });
6799-
6800- if (invalid) {
6801- // For implicit checks, bail out early if anything failed.
6802- if (isImplicitSendableCheck (check))
6803- return true ;
6804- }
6805-
6806- return false ;
6771+ return checkSendabilityOfMemberType (property, propertyType);
68076772 }
68086773
68096774 // / Handle an enum associated value.
68106775 bool operator ()(EnumElementDecl *element, Type elementType) override {
6811- SendableCheckContext context (dc, check);
6776+ return checkSendabilityOfMemberType (element, elementType);
6777+ }
6778+
6779+ private:
6780+ bool checkSendabilityOfMemberType (ValueDecl *member, Type memberType) {
6781+ SendableCheckContext context (dc, check);
68126782 diagnoseNonSendableTypes (
6813- elementType , context,
6814- /* inDerivedConformance*/ Type (), element ->getLoc (),
6783+ memberType , context,
6784+ /* inDerivedConformance*/ Type (), member ->getLoc (),
68156785 [&](Type type, DiagnosticBehavior behavior) {
6816- auto preconcurrency = context.preconcurrencyBehavior (type);
6786+ auto preconcurrencyBehavior = context.preconcurrencyBehavior (type);
68176787 if (isImplicitSendableCheck (check)) {
68186788 // If this is for an externally-visible conformance, fail.
68196789 if (check == SendableCheck::ImplicitForExternallyVisible) {
@@ -6823,21 +6793,29 @@ static bool checkSendableInstanceStorage(
68236793
68246794 // If we are to ignore this diagnostic, just continue.
68256795 if (behavior == DiagnosticBehavior::Ignore ||
6826- preconcurrency == DiagnosticBehavior::Ignore)
6796+ preconcurrencyBehavior == DiagnosticBehavior::Ignore)
68276797 return true ;
68286798
68296799 invalid = true ;
68306800 return true ;
68316801 }
68326802
6833- if (preconcurrency)
6834- behavior = preconcurrency.value ();
6835-
6836- element
6837- ->diagnose (diag::non_concurrent_type_member, type, true ,
6838- element->getName (), nominal)
6839- .limitBehaviorWithPreconcurrency (behavior,
6840- preconcurrency.has_value ());
6803+ // If Sendable came from a `@preconcurrency` protocol the error
6804+ // should be downgraded even with strict concurrency checking to
6805+ // allow clients time to address the new requirement.
6806+ bool fromPreconcurrencyConformance =
6807+ check == SendableCheck::ImpliedByPreconcurrencyProtocol;
6808+
6809+ if (preconcurrencyBehavior)
6810+ behavior = preconcurrencyBehavior.value ();
6811+
6812+ member
6813+ ->diagnose (diag::non_concurrent_type_member, type,
6814+ isa<EnumElementDecl>(member), member->getName (),
6815+ nominal, type->isEqual (memberType))
6816+ .limitBehaviorWithPreconcurrency (
6817+ behavior, fromPreconcurrencyConformance ||
6818+ preconcurrencyBehavior.has_value ());
68416819 return false ;
68426820 });
68436821
@@ -6849,6 +6827,7 @@ static bool checkSendableInstanceStorage(
68496827
68506828 return false ;
68516829 }
6830+
68526831 } visitor(nominal, dc, check);
68536832
68546833 return visitor.visit(nominal, dc) || visitor.invalid;
0 commit comments