@@ -3459,34 +3459,79 @@ static bool checkClassGlobalActorIsolation(
3459
3459
return true ;
3460
3460
}
3461
3461
3462
+ namespace {
3463
+ // / Describes the result of checking override isolation.
3464
+ enum class OverrideIsolationResult {
3465
+ // / The override is permitted.
3466
+ Allowed,
3467
+ // / The override is permitted, but requires a Sendable check.
3468
+ Sendable,
3469
+ // / The override is not permitted.
3470
+ Disallowed,
3471
+ };
3472
+ }
3473
+
3474
+ // / Return the isolation of the declaration overridden by this declaration,
3475
+ // / in the context of the
3476
+ static ActorIsolation getOverriddenIsolationFor (ValueDecl *value) {
3477
+ auto overridden = value->getOverriddenDecl ();
3478
+ assert (overridden && " Doesn't have an overridden declaration" );
3479
+
3480
+ auto isolation = getActorIsolation (overridden);
3481
+ if (!isolation.requiresSubstitution ())
3482
+ return isolation;
3483
+
3484
+ SubstitutionMap subs;
3485
+ if (Type selfType = value->getDeclContext ()->getSelfInterfaceType ()) {
3486
+ subs = selfType->getMemberSubstitutionMap (
3487
+ value->getModuleContext (), overridden);
3488
+ }
3489
+ return isolation.subst (subs);
3490
+ }
3491
+
3462
3492
// / Generally speaking, the isolation of the decl that overrides
3463
3493
// / must match the overridden decl. But there are a number of exceptions,
3464
3494
// / e.g., the decl that overrides can be nonisolated.
3465
- // / \param newIso the isolation of the overriding declaration.
3466
- static bool validOverrideIsolation (ActorIsolation newIso,
3467
- ValueDecl *overriddenDecl,
3468
- ActorIsolation overriddenIso) {
3469
- // If the isolation matches, we're done.
3470
- if (newIso == overriddenIso)
3471
- return true ;
3472
-
3473
- // If the overriding declaration is non-isolated, it's okay.
3474
- if (newIso.isIndependent () || newIso.isUnspecified ())
3475
- return true ;
3495
+ // / \param isolation the isolation of the overriding declaration.
3496
+ static OverrideIsolationResult validOverrideIsolation (
3497
+ ValueDecl *value, ActorIsolation isolation,
3498
+ ValueDecl *overridden, ActorIsolation overriddenIsolation) {
3499
+ ConcreteDeclRef valueRef (value);
3500
+ auto declContext = value->getInnermostDeclContext ();
3501
+ if (auto genericEnv = declContext->getGenericEnvironmentOfContext ()) {
3502
+ valueRef = ConcreteDeclRef (
3503
+ value, genericEnv->getForwardingSubstitutionMap ());
3504
+ }
3476
3505
3477
- // If both are actor-instance isolated, we're done. This wasn't caught by
3478
- // the equality case above because the nominal type describing the actor
3479
- // will differ when we're overriding.
3480
- if (newIso.getKind () == overriddenIso.getKind () &&
3481
- newIso.getKind () == ActorIsolation::ActorInstance)
3482
- return true ;
3506
+ auto refResult = ActorReferenceResult::forReference (
3507
+ valueRef, SourceLoc (), declContext, None, None,
3508
+ isolation, overriddenIsolation);
3509
+ switch (refResult) {
3510
+ case ActorReferenceResult::SameConcurrencyDomain:
3511
+ return OverrideIsolationResult::Allowed;
3512
+
3513
+ case ActorReferenceResult::ExitsActorToNonisolated:
3514
+ return OverrideIsolationResult::Sendable;
3515
+
3516
+ case ActorReferenceResult::EntersActor:
3517
+ // It's okay to enter the actor when the overridden declaration is
3518
+ // asynchronous (because it will do the switch) or is accessible from
3519
+ // anywhere.
3520
+ if (isAsyncDecl (overridden) ||
3521
+ isAccessibleAcrossActors (
3522
+ overridden, refResult.isolation , declContext)) {
3523
+ // FIXME: Perform Sendable checking here because we're entering an
3524
+ // actor.
3525
+ return OverrideIsolationResult::Allowed;
3526
+ }
3483
3527
3484
- // If the overridden declaration is from Objective-C with no actor annotation,
3485
- // allow it.
3486
- if (overriddenDecl ->hasClangNode () && !overriddenIso )
3487
- return true ;
3528
+ // If the overridden declaration is from Objective-C with no actor
3529
+ // annotation, allow it.
3530
+ if (overridden ->hasClangNode () && !overriddenIsolation )
3531
+ return OverrideIsolationResult::Allowed ;
3488
3532
3489
- return false ;
3533
+ return OverrideIsolationResult::Disallowed;
3534
+ }
3490
3535
}
3491
3536
3492
3537
ActorIsolation ActorIsolationRequest::evaluate (
@@ -3548,20 +3593,11 @@ ActorIsolation ActorIsolationRequest::evaluate(
3548
3593
3549
3594
// Look for and remember the overridden declaration's isolation.
3550
3595
Optional<ActorIsolation> overriddenIso;
3551
- ValueDecl *overriddenValue = nullptr ;
3552
- if ( (overriddenValue = value->getOverriddenDecl ()) ) {
3553
- auto iso = getActorIsolation (overriddenValue);
3554
- SubstitutionMap subs;
3555
-
3556
- if (Type selfType = value->getDeclContext ()->getSelfInterfaceType ()) {
3557
- subs = selfType->getMemberSubstitutionMap (
3558
- value->getModuleContext (), overriddenValue);
3559
- }
3560
- iso = iso.subst (subs);
3561
-
3596
+ ValueDecl *overriddenValue = value->getOverriddenDecl ();
3597
+ if (overriddenValue) {
3562
3598
// use the overridden decl's iso as the default isolation for this decl.
3563
- defaultIsolation = iso ;
3564
- overriddenIso = iso ;
3599
+ defaultIsolation = getOverriddenIsolationFor (value) ;
3600
+ overriddenIso = defaultIsolation ;
3565
3601
}
3566
3602
3567
3603
// Function used when returning an inferred isolation.
@@ -3572,8 +3608,16 @@ ActorIsolation ActorIsolationRequest::evaluate(
3572
3608
if (overriddenValue) {
3573
3609
// if the inferred isolation is not valid, then carry-over the overridden
3574
3610
// declaration's isolation as this decl's inferred isolation.
3575
- if (!validOverrideIsolation (inferred, overriddenValue, *overriddenIso))
3611
+ switch (validOverrideIsolation (
3612
+ value, inferred, overriddenValue, *overriddenIso)) {
3613
+ case OverrideIsolationResult::Allowed:
3614
+ case OverrideIsolationResult::Sendable:
3615
+ break ;
3616
+
3617
+ case OverrideIsolationResult::Disallowed:
3576
3618
inferred = *overriddenIso;
3619
+ break ;
3620
+ }
3577
3621
}
3578
3622
3579
3623
// Add an implicit attribute to capture the actor isolation that was
@@ -3843,29 +3887,36 @@ void swift::checkOverrideActorIsolation(ValueDecl *value) {
3843
3887
if (!overridden)
3844
3888
return ;
3845
3889
3846
- // Determine the actor isolation of this declaration .
3890
+ // Determine the actor isolation of the overriding function .
3847
3891
auto isolation = getActorIsolation (value);
3892
+
3893
+ // Determine the actor isolation of the overridden function.
3894
+ auto overriddenIsolation = getOverriddenIsolationFor (value);
3895
+ switch (validOverrideIsolation (
3896
+ value, isolation, overridden, overriddenIsolation)) {
3897
+ case OverrideIsolationResult::Allowed:
3898
+ return ;
3848
3899
3849
- // Determine the actor isolation of the overridden function.=
3850
- auto overriddenIsolation = getActorIsolation (overridden);
3851
-
3852
- if (overriddenIsolation.requiresSubstitution ()) {
3853
- SubstitutionMap subs;
3854
- if (Type selfType = value->getDeclContext ()->getSelfInterfaceType ()) {
3855
- subs = selfType->getMemberSubstitutionMap (
3856
- value->getModuleContext (), overridden);
3857
- }
3900
+ case OverrideIsolationResult::Sendable:
3901
+ // FIXME: Do the Sendable check.
3902
+ return ;
3858
3903
3859
- overriddenIsolation = overriddenIsolation.subst (subs);
3904
+ case OverrideIsolationResult::Disallowed:
3905
+ // Diagnose below.
3906
+ break ;
3860
3907
}
3861
3908
3862
- if (validOverrideIsolation (isolation, overridden, overriddenIsolation))
3863
- return ;
3864
-
3865
3909
// Isolation mismatch. Diagnose it.
3910
+ DiagnosticBehavior behavior = DiagnosticBehavior::Unspecified;
3911
+ if (overridden->hasClangNode () && !overriddenIsolation) {
3912
+ behavior = SendableCheckContext (value->getInnermostDeclContext ())
3913
+ .defaultDiagnosticBehavior ();
3914
+ }
3915
+
3866
3916
value->diagnose (
3867
3917
diag::actor_isolation_override_mismatch, isolation,
3868
- value->getDescriptiveKind (), value->getName (), overriddenIsolation);
3918
+ value->getDescriptiveKind (), value->getName (), overriddenIsolation)
3919
+ .limitBehavior (behavior);
3869
3920
overridden->diagnose (diag::overridden_here);
3870
3921
}
3871
3922
@@ -4866,14 +4917,6 @@ ActorReferenceResult ActorReferenceResult::forExitsActorToNonisolated(
4866
4917
return ActorReferenceResult{ExitsActorToNonisolated, None, isolation};
4867
4918
}
4868
4919
4869
- ActorReferenceResult ActorReferenceResult::forReference (
4870
- ConcreteDeclRef declRef, SourceLoc declRefLoc, const DeclContext *fromDC,
4871
- Optional<VarRefUseEnv> useKind,
4872
- Optional<ReferencedActor> actorInstance) {
4873
- return forReference (declRef, declRefLoc, fromDC, useKind, actorInstance,
4874
- getInnermostIsolatedContext (fromDC));
4875
- }
4876
-
4877
4920
// Determine if two actor isolation contexts are considered to be equivalent.
4878
4921
static bool equivalentIsolationContexts (
4879
4922
const ActorIsolation &lhs, const ActorIsolation &rhs) {
@@ -4892,11 +4935,26 @@ ActorReferenceResult ActorReferenceResult::forReference(
4892
4935
ConcreteDeclRef declRef, SourceLoc declRefLoc, const DeclContext *fromDC,
4893
4936
Optional<VarRefUseEnv> useKind,
4894
4937
Optional<ReferencedActor> actorInstance,
4895
- ActorIsolation contextIsolation) {
4896
- // Compute the isolation of the declaration, adjusted for references.
4897
- auto declIsolation = getActorIsolationForReference (declRef.getDecl (), fromDC);
4898
- if (auto subs = declRef.getSubstitutions ())
4899
- declIsolation = declIsolation.subst (subs);
4938
+ Optional<ActorIsolation> knownDeclIsolation,
4939
+ Optional<ActorIsolation> knownContextIsolation) {
4940
+ // If not provided, compute the isolation of the declaration, adjusted
4941
+ // for references.
4942
+ ActorIsolation declIsolation = ActorIsolation::forUnspecified ();
4943
+ if (knownDeclIsolation) {
4944
+ declIsolation = *knownDeclIsolation;
4945
+ } else {
4946
+ declIsolation = getActorIsolationForReference (declRef.getDecl (), fromDC);
4947
+ if (declIsolation.requiresSubstitution ())
4948
+ declIsolation = declIsolation.subst (declRef.getSubstitutions ());
4949
+ }
4950
+
4951
+ // Compute the isolation of the context, if not provided.
4952
+ ActorIsolation contextIsolation = ActorIsolation::forUnspecified ();
4953
+ if (knownContextIsolation) {
4954
+ contextIsolation = *knownContextIsolation;
4955
+ } else {
4956
+ contextIsolation = getInnermostIsolatedContext (fromDC);
4957
+ }
4900
4958
4901
4959
// When the declaration is not actor-isolated, it can always be accessed
4902
4960
// directly.
0 commit comments