@@ -641,6 +641,7 @@ bool SendableCheckContext::isExplicitSendableConformance() const {
641
641
642
642
case SendableCheck::ImpliedByStandardProtocol:
643
643
case SendableCheck::Implicit:
644
+ case SendableCheck::ImplicitForExternallyVisible:
644
645
return false ;
645
646
}
646
647
}
@@ -754,7 +755,7 @@ DiagnosticBehavior SendableCheckContext::diagnosticBehavior(
754
755
// enclosing inferred types non-Sendable.
755
756
if (defaultBehavior == DiagnosticBehavior::Ignore &&
756
757
nominal->getParentSourceFile () &&
757
- conformanceCheck && *conformanceCheck == SendableCheck::Implicit )
758
+ conformanceCheck && isImplicitSendableCheck ( *conformanceCheck) )
758
759
return DiagnosticBehavior::Warning;
759
760
760
761
return defaultBehavior;
@@ -3877,7 +3878,7 @@ static bool checkSendableInstanceStorage(
3877
3878
bool operator ()(VarDecl *property, Type propertyType) {
3878
3879
// Classes with mutable properties are not Sendable.
3879
3880
if (property->supportsMutation () && isa<ClassDecl>(nominal)) {
3880
- if (check == SendableCheck::Implicit ) {
3881
+ if (isImplicitSendableCheck ( check) ) {
3881
3882
invalid = true ;
3882
3883
return true ;
3883
3884
}
@@ -3898,8 +3899,14 @@ static bool checkSendableInstanceStorage(
3898
3899
diagnoseNonSendableTypes (
3899
3900
propertyType, SendableCheckContext (dc, check), property->getLoc (),
3900
3901
[&](Type type, DiagnosticBehavior behavior) {
3901
- if (check == SendableCheck::Implicit) {
3902
- // If we are to ignore this diagnose, just continue.
3902
+ if (isImplicitSendableCheck (check)) {
3903
+ // If this is for an externally-visible conformance, fail.
3904
+ if (check == SendableCheck::ImplicitForExternallyVisible) {
3905
+ invalid = true ;
3906
+ return true ;
3907
+ }
3908
+
3909
+ // If we are to ignore this diagnostic, just continue.
3903
3910
if (behavior == DiagnosticBehavior::Ignore)
3904
3911
return false ;
3905
3912
@@ -3917,7 +3924,7 @@ static bool checkSendableInstanceStorage(
3917
3924
3918
3925
if (invalid) {
3919
3926
// For implicit checks, bail out early if anything failed.
3920
- if (check == SendableCheck::Implicit )
3927
+ if (isImplicitSendableCheck ( check) )
3921
3928
return true ;
3922
3929
}
3923
3930
@@ -3929,8 +3936,14 @@ static bool checkSendableInstanceStorage(
3929
3936
diagnoseNonSendableTypes (
3930
3937
elementType, SendableCheckContext (dc, check), element->getLoc (),
3931
3938
[&](Type type, DiagnosticBehavior behavior) {
3932
- if (check == SendableCheck::Implicit) {
3933
- // If we are to ignore this diagnose, just continue.
3939
+ if (isImplicitSendableCheck (check)) {
3940
+ // If this is for an externally-visible conformance, fail.
3941
+ if (check == SendableCheck::ImplicitForExternallyVisible) {
3942
+ invalid = true ;
3943
+ return true ;
3944
+ }
3945
+
3946
+ // If we are to ignore this diagnostic, just continue.
3934
3947
if (behavior == DiagnosticBehavior::Ignore)
3935
3948
return false ;
3936
3949
@@ -3948,7 +3961,7 @@ static bool checkSendableInstanceStorage(
3948
3961
3949
3962
if (invalid) {
3950
3963
// For implicit checks, bail out early if anything failed.
3951
- if (check == SendableCheck::Implicit )
3964
+ if (isImplicitSendableCheck ( check) )
3952
3965
return true ;
3953
3966
}
3954
3967
@@ -4177,21 +4190,27 @@ ProtocolConformance *GetImplicitSendableRequest::evaluate(
4177
4190
if (!isa<StructDecl>(nominal) && !isa<EnumDecl>(nominal))
4178
4191
return nullptr ;
4179
4192
4180
- // Public, non-frozen structs and enums defined in Swift don't get implicit
4181
- // Sendable conformances.
4182
- if (!nominal->getASTContext ().LangOpts .EnableInferPublicSendable &&
4183
- nominal->getFormalAccessScope (
4184
- /* useDC=*/ nullptr ,
4185
- /* treatUsableFromInlineAsPublic=*/ true ).isPublic () &&
4186
- !(nominal->hasClangNode () ||
4187
- nominal->getAttrs ().hasAttribute <FixedLayoutAttr>() ||
4188
- nominal->getAttrs ().hasAttribute <FrozenAttr>())) {
4193
+ SendableCheck check;
4194
+
4195
+ // Okay to infer Sendable conformance for non-public types or when
4196
+ // specifically requested.
4197
+ if (nominal->getASTContext ().LangOpts .EnableInferPublicSendable ||
4198
+ !nominal->getFormalAccessScope (
4199
+ /* useDC=*/ nullptr , /* treatUsableFromInlineAsPublic=*/ true )
4200
+ .isPublic ()) {
4201
+ check = SendableCheck::Implicit;
4202
+ } else if (nominal->hasClangNode () ||
4203
+ nominal->getAttrs ().hasAttribute <FixedLayoutAttr>() ||
4204
+ nominal->getAttrs ().hasAttribute <FrozenAttr>()) {
4205
+ // @_frozen public types can also infer Sendable, but be more careful here.
4206
+ check = SendableCheck::ImplicitForExternallyVisible;
4207
+ } else {
4208
+ // No inference.
4189
4209
return nullptr ;
4190
4210
}
4191
4211
4192
4212
// Check the instance storage for Sendable conformance.
4193
- if (checkSendableInstanceStorage (
4194
- nominal, nominal, SendableCheck::Implicit))
4213
+ if (checkSendableInstanceStorage (nominal, nominal, check))
4195
4214
return nullptr ;
4196
4215
4197
4216
return formConformance (nullptr );
0 commit comments