@@ -3396,34 +3396,79 @@ static bool checkClassGlobalActorIsolation(
3396
3396
return true ;
3397
3397
}
3398
3398
3399
+ namespace {
3400
+ // / Describes the result of checking override isolation.
3401
+ enum class OverrideIsolationResult {
3402
+ // / The override is permitted.
3403
+ Allowed,
3404
+ // / The override is permitted, but requires a Sendable check.
3405
+ Sendable,
3406
+ // / The override is not permitted.
3407
+ Disallowed,
3408
+ };
3409
+ }
3410
+
3411
+ // / Return the isolation of the declaration overridden by this declaration,
3412
+ // / in the context of the
3413
+ static ActorIsolation getOverriddenIsolationFor (ValueDecl *value) {
3414
+ auto overridden = value->getOverriddenDecl ();
3415
+ assert (overridden && " Doesn't have an overridden declaration" );
3416
+
3417
+ auto isolation = getActorIsolation (overridden);
3418
+ if (!isolation.requiresSubstitution ())
3419
+ return isolation;
3420
+
3421
+ SubstitutionMap subs;
3422
+ if (Type selfType = value->getDeclContext ()->getSelfInterfaceType ()) {
3423
+ subs = selfType->getMemberSubstitutionMap (
3424
+ value->getModuleContext (), overridden);
3425
+ }
3426
+ return isolation.subst (subs);
3427
+ }
3428
+
3399
3429
// / Generally speaking, the isolation of the decl that overrides
3400
3430
// / must match the overridden decl. But there are a number of exceptions,
3401
3431
// / e.g., the decl that overrides can be nonisolated.
3402
- // / \param newIso the isolation of the overriding declaration.
3403
- static bool validOverrideIsolation (ActorIsolation newIso,
3404
- ValueDecl *overriddenDecl,
3405
- ActorIsolation overriddenIso) {
3406
- // If the isolation matches, we're done.
3407
- if (newIso == overriddenIso)
3408
- return true ;
3409
-
3410
- // If the overriding declaration is non-isolated, it's okay.
3411
- if (newIso.isIndependent () || newIso.isUnspecified ())
3412
- return true ;
3432
+ // / \param isolation the isolation of the overriding declaration.
3433
+ static OverrideIsolationResult validOverrideIsolation (
3434
+ ValueDecl *value, ActorIsolation isolation,
3435
+ ValueDecl *overridden, ActorIsolation overriddenIsolation) {
3436
+ ConcreteDeclRef valueRef (value);
3437
+ auto declContext = value->getInnermostDeclContext ();
3438
+ if (auto genericEnv = declContext->getGenericEnvironmentOfContext ()) {
3439
+ valueRef = ConcreteDeclRef (
3440
+ value, genericEnv->getForwardingSubstitutionMap ());
3441
+ }
3413
3442
3414
- // If both are actor-instance isolated, we're done. This wasn't caught by
3415
- // the equality case above because the nominal type describing the actor
3416
- // will differ when we're overriding.
3417
- if (newIso.getKind () == overriddenIso.getKind () &&
3418
- newIso.getKind () == ActorIsolation::ActorInstance)
3419
- return true ;
3443
+ auto refResult = ActorReferenceResult::forReference (
3444
+ valueRef, SourceLoc (), declContext, None, None,
3445
+ isolation, overriddenIsolation);
3446
+ switch (refResult) {
3447
+ case ActorReferenceResult::SameConcurrencyDomain:
3448
+ return OverrideIsolationResult::Allowed;
3449
+
3450
+ case ActorReferenceResult::ExitsActorToNonisolated:
3451
+ return OverrideIsolationResult::Sendable;
3452
+
3453
+ case ActorReferenceResult::EntersActor:
3454
+ // It's okay to enter the actor when the overridden declaration is
3455
+ // asynchronous (because it will do the switch) or is accessible from
3456
+ // anywhere.
3457
+ if (isAsyncDecl (overridden) ||
3458
+ isAccessibleAcrossActors (
3459
+ overridden, refResult.isolation , declContext)) {
3460
+ // FIXME: Perform Sendable checking here because we're entering an
3461
+ // actor.
3462
+ return OverrideIsolationResult::Allowed;
3463
+ }
3420
3464
3421
- // If the overridden declaration is from Objective-C with no actor annotation,
3422
- // allow it.
3423
- if (overriddenDecl ->hasClangNode () && !overriddenIso )
3424
- return true ;
3465
+ // If the overridden declaration is from Objective-C with no actor
3466
+ // annotation, allow it.
3467
+ if (overridden ->hasClangNode () && !overriddenIsolation )
3468
+ return OverrideIsolationResult::Allowed ;
3425
3469
3426
- return false ;
3470
+ return OverrideIsolationResult::Disallowed;
3471
+ }
3427
3472
}
3428
3473
3429
3474
ActorIsolation ActorIsolationRequest::evaluate (
@@ -3485,20 +3530,11 @@ ActorIsolation ActorIsolationRequest::evaluate(
3485
3530
3486
3531
// Look for and remember the overridden declaration's isolation.
3487
3532
Optional<ActorIsolation> overriddenIso;
3488
- ValueDecl *overriddenValue = nullptr ;
3489
- if ( (overriddenValue = value->getOverriddenDecl ()) ) {
3490
- auto iso = getActorIsolation (overriddenValue);
3491
- SubstitutionMap subs;
3492
-
3493
- if (Type selfType = value->getDeclContext ()->getSelfInterfaceType ()) {
3494
- subs = selfType->getMemberSubstitutionMap (
3495
- value->getModuleContext (), overriddenValue);
3496
- }
3497
- iso = iso.subst (subs);
3498
-
3533
+ ValueDecl *overriddenValue = value->getOverriddenDecl ();
3534
+ if (overriddenValue) {
3499
3535
// use the overridden decl's iso as the default isolation for this decl.
3500
- defaultIsolation = iso ;
3501
- overriddenIso = iso ;
3536
+ defaultIsolation = getOverriddenIsolationFor (value) ;
3537
+ overriddenIso = defaultIsolation ;
3502
3538
}
3503
3539
3504
3540
// Function used when returning an inferred isolation.
@@ -3509,8 +3545,16 @@ ActorIsolation ActorIsolationRequest::evaluate(
3509
3545
if (overriddenValue) {
3510
3546
// if the inferred isolation is not valid, then carry-over the overridden
3511
3547
// declaration's isolation as this decl's inferred isolation.
3512
- if (!validOverrideIsolation (inferred, overriddenValue, *overriddenIso))
3548
+ switch (validOverrideIsolation (
3549
+ value, inferred, overriddenValue, *overriddenIso)) {
3550
+ case OverrideIsolationResult::Allowed:
3551
+ case OverrideIsolationResult::Sendable:
3552
+ break ;
3553
+
3554
+ case OverrideIsolationResult::Disallowed:
3513
3555
inferred = *overriddenIso;
3556
+ break ;
3557
+ }
3514
3558
}
3515
3559
3516
3560
// Add an implicit attribute to capture the actor isolation that was
@@ -3779,29 +3823,36 @@ void swift::checkOverrideActorIsolation(ValueDecl *value) {
3779
3823
if (!overridden)
3780
3824
return ;
3781
3825
3782
- // Determine the actor isolation of this declaration .
3826
+ // Determine the actor isolation of the overriding function .
3783
3827
auto isolation = getActorIsolation (value);
3828
+
3829
+ // Determine the actor isolation of the overridden function.
3830
+ auto overriddenIsolation = getOverriddenIsolationFor (value);
3831
+ switch (validOverrideIsolation (
3832
+ value, isolation, overridden, overriddenIsolation)) {
3833
+ case OverrideIsolationResult::Allowed:
3834
+ return ;
3784
3835
3785
- // Determine the actor isolation of the overridden function.=
3786
- auto overriddenIsolation = getActorIsolation (overridden);
3787
-
3788
- if (overriddenIsolation.requiresSubstitution ()) {
3789
- SubstitutionMap subs;
3790
- if (Type selfType = value->getDeclContext ()->getSelfInterfaceType ()) {
3791
- subs = selfType->getMemberSubstitutionMap (
3792
- value->getModuleContext (), overridden);
3793
- }
3836
+ case OverrideIsolationResult::Sendable:
3837
+ // FIXME: Do the Sendable check.
3838
+ return ;
3794
3839
3795
- overriddenIsolation = overriddenIsolation.subst (subs);
3840
+ case OverrideIsolationResult::Disallowed:
3841
+ // Diagnose below.
3842
+ break ;
3796
3843
}
3797
3844
3798
- if (validOverrideIsolation (isolation, overridden, overriddenIsolation))
3799
- return ;
3800
-
3801
3845
// Isolation mismatch. Diagnose it.
3846
+ DiagnosticBehavior behavior = DiagnosticBehavior::Unspecified;
3847
+ if (overridden->hasClangNode () && !overriddenIsolation) {
3848
+ behavior = SendableCheckContext (value->getInnermostDeclContext ())
3849
+ .defaultDiagnosticBehavior ();
3850
+ }
3851
+
3802
3852
value->diagnose (
3803
3853
diag::actor_isolation_override_mismatch, isolation,
3804
- value->getDescriptiveKind (), value->getName (), overriddenIsolation);
3854
+ value->getDescriptiveKind (), value->getName (), overriddenIsolation)
3855
+ .limitBehavior (behavior);
3805
3856
overridden->diagnose (diag::overridden_here);
3806
3857
}
3807
3858
@@ -4796,14 +4847,6 @@ ActorReferenceResult ActorReferenceResult::forExitsActorToNonisolated(
4796
4847
return ActorReferenceResult{ExitsActorToNonisolated, None, isolation};
4797
4848
}
4798
4849
4799
- ActorReferenceResult ActorReferenceResult::forReference (
4800
- ConcreteDeclRef declRef, SourceLoc declRefLoc, const DeclContext *fromDC,
4801
- Optional<VarRefUseEnv> useKind,
4802
- Optional<ReferencedActor> actorInstance) {
4803
- return forReference (declRef, declRefLoc, fromDC, useKind, actorInstance,
4804
- getInnermostIsolatedContext (fromDC));
4805
- }
4806
-
4807
4850
// Determine if two actor isolation contexts are considered to be equivalent.
4808
4851
static bool equivalentIsolationContexts (
4809
4852
const ActorIsolation &lhs, const ActorIsolation &rhs) {
@@ -4822,11 +4865,26 @@ ActorReferenceResult ActorReferenceResult::forReference(
4822
4865
ConcreteDeclRef declRef, SourceLoc declRefLoc, const DeclContext *fromDC,
4823
4866
Optional<VarRefUseEnv> useKind,
4824
4867
Optional<ReferencedActor> actorInstance,
4825
- ActorIsolation contextIsolation) {
4826
- // Compute the isolation of the declaration, adjusted for references.
4827
- auto declIsolation = getActorIsolationForReference (declRef.getDecl (), fromDC);
4828
- if (auto subs = declRef.getSubstitutions ())
4829
- declIsolation = declIsolation.subst (subs);
4868
+ Optional<ActorIsolation> knownDeclIsolation,
4869
+ Optional<ActorIsolation> knownContextIsolation) {
4870
+ // If not provided, compute the isolation of the declaration, adjusted
4871
+ // for references.
4872
+ ActorIsolation declIsolation = ActorIsolation::forUnspecified ();
4873
+ if (knownDeclIsolation) {
4874
+ declIsolation = *knownDeclIsolation;
4875
+ } else {
4876
+ declIsolation = getActorIsolationForReference (declRef.getDecl (), fromDC);
4877
+ if (declIsolation.requiresSubstitution ())
4878
+ declIsolation = declIsolation.subst (declRef.getSubstitutions ());
4879
+ }
4880
+
4881
+ // Compute the isolation of the context, if not provided.
4882
+ ActorIsolation contextIsolation = ActorIsolation::forUnspecified ();
4883
+ if (knownContextIsolation) {
4884
+ contextIsolation = *knownContextIsolation;
4885
+ } else {
4886
+ contextIsolation = getInnermostIsolatedContext (fromDC);
4887
+ }
4830
4888
4831
4889
// When the declaration is not actor-isolated, it can always be accessed
4832
4890
// directly.
0 commit comments