@@ -748,6 +748,7 @@ bool SendableCheckContext::isExplicitSendableConformance() const {
748
748
749
749
case SendableCheck::ImpliedByStandardProtocol:
750
750
case SendableCheck::Implicit:
751
+ case SendableCheck::ImplicitForExternallyVisible:
751
752
return false ;
752
753
}
753
754
}
@@ -861,7 +862,7 @@ DiagnosticBehavior SendableCheckContext::diagnosticBehavior(
861
862
// enclosing inferred types non-Sendable.
862
863
if (defaultBehavior == DiagnosticBehavior::Ignore &&
863
864
nominal->getParentSourceFile () &&
864
- conformanceCheck && *conformanceCheck == SendableCheck::Implicit )
865
+ conformanceCheck && isImplicitSendableCheck ( *conformanceCheck) )
865
866
return DiagnosticBehavior::Warning;
866
867
867
868
return defaultBehavior;
@@ -4053,7 +4054,7 @@ static bool checkSendableInstanceStorage(
4053
4054
bool operator ()(VarDecl *property, Type propertyType) {
4054
4055
// Classes with mutable properties are not Sendable.
4055
4056
if (property->supportsMutation () && isa<ClassDecl>(nominal)) {
4056
- if (check == SendableCheck::Implicit ) {
4057
+ if (isImplicitSendableCheck ( check) ) {
4057
4058
invalid = true ;
4058
4059
return true ;
4059
4060
}
@@ -4074,8 +4075,14 @@ static bool checkSendableInstanceStorage(
4074
4075
diagnoseNonSendableTypes (
4075
4076
propertyType, SendableCheckContext (dc, check), property->getLoc (),
4076
4077
[&](Type type, DiagnosticBehavior behavior) {
4077
- if (check == SendableCheck::Implicit) {
4078
- // If we are to ignore this diagnose, just continue.
4078
+ if (isImplicitSendableCheck (check)) {
4079
+ // If this is for an externally-visible conformance, fail.
4080
+ if (check == SendableCheck::ImplicitForExternallyVisible) {
4081
+ invalid = true ;
4082
+ return true ;
4083
+ }
4084
+
4085
+ // If we are to ignore this diagnostic, just continue.
4079
4086
if (behavior == DiagnosticBehavior::Ignore)
4080
4087
return false ;
4081
4088
@@ -4093,7 +4100,7 @@ static bool checkSendableInstanceStorage(
4093
4100
4094
4101
if (invalid) {
4095
4102
// For implicit checks, bail out early if anything failed.
4096
- if (check == SendableCheck::Implicit )
4103
+ if (isImplicitSendableCheck ( check) )
4097
4104
return true ;
4098
4105
}
4099
4106
@@ -4105,8 +4112,14 @@ static bool checkSendableInstanceStorage(
4105
4112
diagnoseNonSendableTypes (
4106
4113
elementType, SendableCheckContext (dc, check), element->getLoc (),
4107
4114
[&](Type type, DiagnosticBehavior behavior) {
4108
- if (check == SendableCheck::Implicit) {
4109
- // If we are to ignore this diagnose, just continue.
4115
+ if (isImplicitSendableCheck (check)) {
4116
+ // If this is for an externally-visible conformance, fail.
4117
+ if (check == SendableCheck::ImplicitForExternallyVisible) {
4118
+ invalid = true ;
4119
+ return true ;
4120
+ }
4121
+
4122
+ // If we are to ignore this diagnostic, just continue.
4110
4123
if (behavior == DiagnosticBehavior::Ignore)
4111
4124
return false ;
4112
4125
@@ -4124,7 +4137,7 @@ static bool checkSendableInstanceStorage(
4124
4137
4125
4138
if (invalid) {
4126
4139
// For implicit checks, bail out early if anything failed.
4127
- if (check == SendableCheck::Implicit )
4140
+ if (isImplicitSendableCheck ( check) )
4128
4141
return true ;
4129
4142
}
4130
4143
@@ -4352,21 +4365,27 @@ ProtocolConformance *GetImplicitSendableRequest::evaluate(
4352
4365
if (!isa<StructDecl>(nominal) && !isa<EnumDecl>(nominal))
4353
4366
return nullptr ;
4354
4367
4355
- // Public, non-frozen structs and enums defined in Swift don't get implicit
4356
- // Sendable conformances.
4357
- if (!nominal->getASTContext ().LangOpts .EnableInferPublicSendable &&
4358
- nominal->getFormalAccessScope (
4359
- /* useDC=*/ nullptr ,
4360
- /* treatUsableFromInlineAsPublic=*/ true ).isPublic () &&
4361
- !(nominal->hasClangNode () ||
4362
- nominal->getAttrs ().hasAttribute <FixedLayoutAttr>() ||
4363
- nominal->getAttrs ().hasAttribute <FrozenAttr>())) {
4368
+ SendableCheck check;
4369
+
4370
+ // Okay to infer Sendable conformance for non-public types or when
4371
+ // specifically requested.
4372
+ if (nominal->getASTContext ().LangOpts .EnableInferPublicSendable ||
4373
+ !nominal->getFormalAccessScope (
4374
+ /* useDC=*/ nullptr , /* treatUsableFromInlineAsPublic=*/ true )
4375
+ .isPublic ()) {
4376
+ check = SendableCheck::Implicit;
4377
+ } else if (nominal->hasClangNode () ||
4378
+ nominal->getAttrs ().hasAttribute <FixedLayoutAttr>() ||
4379
+ nominal->getAttrs ().hasAttribute <FrozenAttr>()) {
4380
+ // @_frozen public types can also infer Sendable, but be more careful here.
4381
+ check = SendableCheck::ImplicitForExternallyVisible;
4382
+ } else {
4383
+ // No inference.
4364
4384
return nullptr ;
4365
4385
}
4366
4386
4367
4387
// Check the instance storage for Sendable conformance.
4368
- if (checkSendableInstanceStorage (
4369
- nominal, nominal, SendableCheck::Implicit))
4388
+ if (checkSendableInstanceStorage (nominal, nominal, check))
4370
4389
return nullptr ;
4371
4390
4372
4391
return formConformance (nullptr );
0 commit comments