@@ -3428,34 +3428,79 @@ static bool checkClassGlobalActorIsolation(
3428
3428
return true ;
3429
3429
}
3430
3430
3431
+ namespace {
3432
+ // / Describes the result of checking override isolation.
3433
+ enum class OverrideIsolationResult {
3434
+ // / The override is permitted.
3435
+ Allowed,
3436
+ // / The override is permitted, but requires a Sendable check.
3437
+ Sendable,
3438
+ // / The override is not permitted.
3439
+ Disallowed,
3440
+ };
3441
+ }
3442
+
3443
+ // / Return the isolation of the declaration overridden by this declaration,
3444
+ // / in the context of the
3445
+ static ActorIsolation getOverriddenIsolationFor (ValueDecl *value) {
3446
+ auto overridden = value->getOverriddenDecl ();
3447
+ assert (overridden && " Doesn't have an overridden declaration" );
3448
+
3449
+ auto isolation = getActorIsolation (overridden);
3450
+ if (!isolation.requiresSubstitution ())
3451
+ return isolation;
3452
+
3453
+ SubstitutionMap subs;
3454
+ if (Type selfType = value->getDeclContext ()->getSelfInterfaceType ()) {
3455
+ subs = selfType->getMemberSubstitutionMap (
3456
+ value->getModuleContext (), overridden);
3457
+ }
3458
+ return isolation.subst (subs);
3459
+ }
3460
+
3431
3461
// / Generally speaking, the isolation of the decl that overrides
3432
3462
// / must match the overridden decl. But there are a number of exceptions,
3433
3463
// / e.g., the decl that overrides can be nonisolated.
3434
- // / \param newIso the isolation of the overriding declaration.
3435
- static bool validOverrideIsolation (ActorIsolation newIso,
3436
- ValueDecl *overriddenDecl,
3437
- ActorIsolation overriddenIso) {
3438
- // If the isolation matches, we're done.
3439
- if (newIso == overriddenIso)
3440
- return true ;
3441
-
3442
- // If the overriding declaration is non-isolated, it's okay.
3443
- if (newIso.isIndependent () || newIso.isUnspecified ())
3444
- return true ;
3464
+ // / \param isolation the isolation of the overriding declaration.
3465
+ static OverrideIsolationResult validOverrideIsolation (
3466
+ ValueDecl *value, ActorIsolation isolation,
3467
+ ValueDecl *overridden, ActorIsolation overriddenIsolation) {
3468
+ ConcreteDeclRef valueRef (value);
3469
+ auto declContext = value->getInnermostDeclContext ();
3470
+ if (auto genericEnv = declContext->getGenericEnvironmentOfContext ()) {
3471
+ valueRef = ConcreteDeclRef (
3472
+ value, genericEnv->getForwardingSubstitutionMap ());
3473
+ }
3445
3474
3446
- // If both are actor-instance isolated, we're done. This wasn't caught by
3447
- // the equality case above because the nominal type describing the actor
3448
- // will differ when we're overriding.
3449
- if (newIso.getKind () == overriddenIso.getKind () &&
3450
- newIso.getKind () == ActorIsolation::ActorInstance)
3451
- return true ;
3475
+ auto refResult = ActorReferenceResult::forReference (
3476
+ valueRef, SourceLoc (), declContext, None, None,
3477
+ isolation, overriddenIsolation);
3478
+ switch (refResult) {
3479
+ case ActorReferenceResult::SameConcurrencyDomain:
3480
+ return OverrideIsolationResult::Allowed;
3481
+
3482
+ case ActorReferenceResult::ExitsActorToNonisolated:
3483
+ return OverrideIsolationResult::Sendable;
3484
+
3485
+ case ActorReferenceResult::EntersActor:
3486
+ // It's okay to enter the actor when the overridden declaration is
3487
+ // asynchronous (because it will do the switch) or is accessible from
3488
+ // anywhere.
3489
+ if (isAsyncDecl (overridden) ||
3490
+ isAccessibleAcrossActors (
3491
+ overridden, refResult.isolation , declContext)) {
3492
+ // FIXME: Perform Sendable checking here because we're entering an
3493
+ // actor.
3494
+ return OverrideIsolationResult::Allowed;
3495
+ }
3452
3496
3453
- // If the overridden declaration is from Objective-C with no actor annotation,
3454
- // allow it.
3455
- if (overriddenDecl ->hasClangNode () && !overriddenIso )
3456
- return true ;
3497
+ // If the overridden declaration is from Objective-C with no actor
3498
+ // annotation, allow it.
3499
+ if (overridden ->hasClangNode () && !overriddenIsolation )
3500
+ return OverrideIsolationResult::Allowed ;
3457
3501
3458
- return false ;
3502
+ return OverrideIsolationResult::Disallowed;
3503
+ }
3459
3504
}
3460
3505
3461
3506
ActorIsolation ActorIsolationRequest::evaluate (
@@ -3517,20 +3562,11 @@ ActorIsolation ActorIsolationRequest::evaluate(
3517
3562
3518
3563
// Look for and remember the overridden declaration's isolation.
3519
3564
Optional<ActorIsolation> overriddenIso;
3520
- ValueDecl *overriddenValue = nullptr ;
3521
- if ( (overriddenValue = value->getOverriddenDecl ()) ) {
3522
- auto iso = getActorIsolation (overriddenValue);
3523
- SubstitutionMap subs;
3524
-
3525
- if (Type selfType = value->getDeclContext ()->getSelfInterfaceType ()) {
3526
- subs = selfType->getMemberSubstitutionMap (
3527
- value->getModuleContext (), overriddenValue);
3528
- }
3529
- iso = iso.subst (subs);
3530
-
3565
+ ValueDecl *overriddenValue = value->getOverriddenDecl ();
3566
+ if (overriddenValue) {
3531
3567
// use the overridden decl's iso as the default isolation for this decl.
3532
- defaultIsolation = iso ;
3533
- overriddenIso = iso ;
3568
+ defaultIsolation = getOverriddenIsolationFor (value) ;
3569
+ overriddenIso = defaultIsolation ;
3534
3570
}
3535
3571
3536
3572
// Function used when returning an inferred isolation.
@@ -3541,8 +3577,16 @@ ActorIsolation ActorIsolationRequest::evaluate(
3541
3577
if (overriddenValue) {
3542
3578
// if the inferred isolation is not valid, then carry-over the overridden
3543
3579
// declaration's isolation as this decl's inferred isolation.
3544
- if (!validOverrideIsolation (inferred, overriddenValue, *overriddenIso))
3580
+ switch (validOverrideIsolation (
3581
+ value, inferred, overriddenValue, *overriddenIso)) {
3582
+ case OverrideIsolationResult::Allowed:
3583
+ case OverrideIsolationResult::Sendable:
3584
+ break ;
3585
+
3586
+ case OverrideIsolationResult::Disallowed:
3545
3587
inferred = *overriddenIso;
3588
+ break ;
3589
+ }
3546
3590
}
3547
3591
3548
3592
// Add an implicit attribute to capture the actor isolation that was
@@ -3811,29 +3855,36 @@ void swift::checkOverrideActorIsolation(ValueDecl *value) {
3811
3855
if (!overridden)
3812
3856
return ;
3813
3857
3814
- // Determine the actor isolation of this declaration .
3858
+ // Determine the actor isolation of the overriding function .
3815
3859
auto isolation = getActorIsolation (value);
3860
+
3861
+ // Determine the actor isolation of the overridden function.
3862
+ auto overriddenIsolation = getOverriddenIsolationFor (value);
3863
+ switch (validOverrideIsolation (
3864
+ value, isolation, overridden, overriddenIsolation)) {
3865
+ case OverrideIsolationResult::Allowed:
3866
+ return ;
3816
3867
3817
- // Determine the actor isolation of the overridden function.=
3818
- auto overriddenIsolation = getActorIsolation (overridden);
3819
-
3820
- if (overriddenIsolation.requiresSubstitution ()) {
3821
- SubstitutionMap subs;
3822
- if (Type selfType = value->getDeclContext ()->getSelfInterfaceType ()) {
3823
- subs = selfType->getMemberSubstitutionMap (
3824
- value->getModuleContext (), overridden);
3825
- }
3868
+ case OverrideIsolationResult::Sendable:
3869
+ // FIXME: Do the Sendable check.
3870
+ return ;
3826
3871
3827
- overriddenIsolation = overriddenIsolation.subst (subs);
3872
+ case OverrideIsolationResult::Disallowed:
3873
+ // Diagnose below.
3874
+ break ;
3828
3875
}
3829
3876
3830
- if (validOverrideIsolation (isolation, overridden, overriddenIsolation))
3831
- return ;
3832
-
3833
3877
// Isolation mismatch. Diagnose it.
3878
+ DiagnosticBehavior behavior = DiagnosticBehavior::Unspecified;
3879
+ if (overridden->hasClangNode () && !overriddenIsolation) {
3880
+ behavior = SendableCheckContext (value->getInnermostDeclContext ())
3881
+ .defaultDiagnosticBehavior ();
3882
+ }
3883
+
3834
3884
value->diagnose (
3835
3885
diag::actor_isolation_override_mismatch, isolation,
3836
- value->getDescriptiveKind (), value->getName (), overriddenIsolation);
3886
+ value->getDescriptiveKind (), value->getName (), overriddenIsolation)
3887
+ .limitBehavior (behavior);
3837
3888
overridden->diagnose (diag::overridden_here);
3838
3889
}
3839
3890
@@ -4828,14 +4879,6 @@ ActorReferenceResult ActorReferenceResult::forExitsActorToNonisolated(
4828
4879
return ActorReferenceResult{ExitsActorToNonisolated, None, isolation};
4829
4880
}
4830
4881
4831
- ActorReferenceResult ActorReferenceResult::forReference (
4832
- ConcreteDeclRef declRef, SourceLoc declRefLoc, const DeclContext *fromDC,
4833
- Optional<VarRefUseEnv> useKind,
4834
- Optional<ReferencedActor> actorInstance) {
4835
- return forReference (declRef, declRefLoc, fromDC, useKind, actorInstance,
4836
- getInnermostIsolatedContext (fromDC));
4837
- }
4838
-
4839
4882
// Determine if two actor isolation contexts are considered to be equivalent.
4840
4883
static bool equivalentIsolationContexts (
4841
4884
const ActorIsolation &lhs, const ActorIsolation &rhs) {
@@ -4854,11 +4897,26 @@ ActorReferenceResult ActorReferenceResult::forReference(
4854
4897
ConcreteDeclRef declRef, SourceLoc declRefLoc, const DeclContext *fromDC,
4855
4898
Optional<VarRefUseEnv> useKind,
4856
4899
Optional<ReferencedActor> actorInstance,
4857
- ActorIsolation contextIsolation) {
4858
- // Compute the isolation of the declaration, adjusted for references.
4859
- auto declIsolation = getActorIsolationForReference (declRef.getDecl (), fromDC);
4860
- if (auto subs = declRef.getSubstitutions ())
4861
- declIsolation = declIsolation.subst (subs);
4900
+ Optional<ActorIsolation> knownDeclIsolation,
4901
+ Optional<ActorIsolation> knownContextIsolation) {
4902
+ // If not provided, compute the isolation of the declaration, adjusted
4903
+ // for references.
4904
+ ActorIsolation declIsolation = ActorIsolation::forUnspecified ();
4905
+ if (knownDeclIsolation) {
4906
+ declIsolation = *knownDeclIsolation;
4907
+ } else {
4908
+ declIsolation = getActorIsolationForReference (declRef.getDecl (), fromDC);
4909
+ if (declIsolation.requiresSubstitution ())
4910
+ declIsolation = declIsolation.subst (declRef.getSubstitutions ());
4911
+ }
4912
+
4913
+ // Compute the isolation of the context, if not provided.
4914
+ ActorIsolation contextIsolation = ActorIsolation::forUnspecified ();
4915
+ if (knownContextIsolation) {
4916
+ contextIsolation = *knownContextIsolation;
4917
+ } else {
4918
+ contextIsolation = getInnermostIsolatedContext (fromDC);
4919
+ }
4862
4920
4863
4921
// When the declaration is not actor-isolated, it can always be accessed
4864
4922
// directly.
0 commit comments