@@ -797,7 +797,7 @@ bool SendableCheckContext::warnInMinimalChecking() const {
797
797
case SendableCheck::Explicit:
798
798
return true ;
799
799
800
- case SendableCheck::ImpliedByStandardProtocol :
800
+ case SendableCheck::ImpliedByPreconcurrencyProtocol :
801
801
case SendableCheck::Implicit:
802
802
case SendableCheck::ImplicitForExternallyVisible:
803
803
return false ;
@@ -6748,11 +6748,16 @@ static bool checkSendableInstanceStorage(
6748
6748
if (property->supportsMutation () && isolation.isUnspecified ()) {
6749
6749
auto behavior =
6750
6750
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;
6751
6756
if (behavior != DiagnosticBehavior::Ignore) {
6752
6757
property
6753
6758
->diagnose (diag::concurrent_value_class_mutable_property,
6754
6759
property->getName (), nominal)
6755
- .limitBehaviorUntilSwiftVersion (behavior, 6 );
6760
+ .limitBehaviorWithPreconcurrency (behavior, preconcurrency );
6756
6761
}
6757
6762
invalid = invalid || (behavior == DiagnosticBehavior::Unspecified);
6758
6763
return true ;
@@ -6763,57 +6768,22 @@ static bool checkSendableInstanceStorage(
6763
6768
}
6764
6769
}
6765
6770
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);
6807
6772
}
6808
6773
6809
6774
// / Handle an enum associated value.
6810
6775
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);
6812
6782
diagnoseNonSendableTypes (
6813
- elementType , context,
6814
- /* inDerivedConformance*/ Type (), element ->getLoc (),
6783
+ memberType , context,
6784
+ /* inDerivedConformance*/ Type (), member ->getLoc (),
6815
6785
[&](Type type, DiagnosticBehavior behavior) {
6816
- auto preconcurrency = context.preconcurrencyBehavior (type);
6786
+ auto preconcurrencyBehavior = context.preconcurrencyBehavior (type);
6817
6787
if (isImplicitSendableCheck (check)) {
6818
6788
// If this is for an externally-visible conformance, fail.
6819
6789
if (check == SendableCheck::ImplicitForExternallyVisible) {
@@ -6823,21 +6793,29 @@ static bool checkSendableInstanceStorage(
6823
6793
6824
6794
// If we are to ignore this diagnostic, just continue.
6825
6795
if (behavior == DiagnosticBehavior::Ignore ||
6826
- preconcurrency == DiagnosticBehavior::Ignore)
6796
+ preconcurrencyBehavior == DiagnosticBehavior::Ignore)
6827
6797
return true ;
6828
6798
6829
6799
invalid = true ;
6830
6800
return true ;
6831
6801
}
6832
6802
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 ());
6841
6819
return false ;
6842
6820
});
6843
6821
@@ -6849,6 +6827,7 @@ static bool checkSendableInstanceStorage(
6849
6827
6850
6828
return false ;
6851
6829
}
6830
+
6852
6831
} visitor(nominal, dc, check);
6853
6832
6854
6833
return visitor.visit(nominal, dc) || visitor.invalid;
0 commit comments