@@ -1597,6 +1597,10 @@ static void noteGlobalActorOnContext(DeclContext *dc, Type globalActor) {
15971597 }
15981598}
15991599
1600+ static bool isAccessibleAcrossActors (
1601+ ValueDecl *value, const ActorIsolation &isolation,
1602+ const DeclContext *fromDC, Optional<ReferencedActor> actorInstance);
1603+
16001604namespace {
16011605 // / Check for adherence to the actor isolation rules, emitting errors
16021606 // / when actor-isolated declarations are used in an unsafe manner.
@@ -2696,72 +2700,49 @@ namespace {
26962700 bool checkKeyPathExpr (KeyPathExpr *keyPath) {
26972701 bool diagnosed = false ;
26982702
2699- // returns None if it is not a 'let'-bound var decl. Otherwise,
2700- // the bool indicates whether a diagnostic was emitted.
2701- auto checkLetBoundVarDecl = [&](KeyPathExpr::Component const & component)
2702- -> Optional<bool > {
2703- auto decl = component.getDeclRef ().getDecl ();
2704- if (auto varDecl = dyn_cast<VarDecl>(decl)) {
2705- if (varDecl->isLet ()) {
2706- auto type = component.getComponentType ();
2707- if (shouldDiagnoseExistingDataRaces (getDeclContext ()) &&
2708- diagnoseNonSendableTypes (
2709- type, getDeclContext (), component.getLoc (),
2710- diag::non_sendable_keypath_access))
2711- return true ;
2712-
2713- return false ;
2714- }
2715- }
2716- return None;
2717- };
2718-
27192703 // check the components of the keypath.
27202704 for (const auto &component : keyPath->getComponents ()) {
27212705 // The decl referred to by the path component cannot be within an actor.
27222706 if (component.hasDeclRef ()) {
27232707 auto concDecl = component.getDeclRef ();
2724- auto isolation = ActorIsolationRestriction::forDeclaration (
2725- concDecl, getDeclContext ());
2726-
2727- switch (isolation.getKind ()) {
2728- case ActorIsolationRestriction::Unsafe:
2729- case ActorIsolationRestriction::Unrestricted:
2730- break ; // OK. Does not refer to an actor-isolated member.
2731-
2732- case ActorIsolationRestriction::GlobalActorUnsafe:
2733- // Only check if we're in code that's adopted concurrency features.
2734- if (!shouldDiagnoseExistingDataRaces (getDeclContext ()))
2735- break ; // do not check
2736-
2737- LLVM_FALLTHROUGH; // otherwise, perform checking
2708+ auto decl = concDecl.getDecl ();
2709+ auto isolation = getActorIsolationForReference (
2710+ decl, getDeclContext ());
2711+ switch (isolation) {
2712+ case ActorIsolation::Independent:
2713+ case ActorIsolation::Unspecified:
2714+ break ;
27382715
2739- case ActorIsolationRestriction::GlobalActor:
2716+ case ActorIsolation::GlobalActor:
2717+ case ActorIsolation::GlobalActorUnsafe:
27402718 // Disable global actor checking for now.
2741- if (!ctx.LangOpts .isSwiftVersionAtLeast (6 ))
2719+ if (isolation.isGlobalActor () &&
2720+ !ctx.LangOpts .isSwiftVersionAtLeast (6 ))
27422721 break ;
27432722
2744- LLVM_FALLTHROUGH; // otherwise, it's invalid so diagnose it.
2723+ LLVM_FALLTHROUGH;
27452724
2746- case ActorIsolationRestriction::CrossActorSelf:
2747- // 'let'-bound decls with this isolation are OK, just check them.
2748- if (auto wasLetBound = checkLetBoundVarDecl (component)) {
2749- diagnosed = wasLetBound.getValue ();
2725+ case ActorIsolation::ActorInstance:
2726+ // If this entity is always accessible across actors, just check
2727+ // Sendable.
2728+ if (isAccessibleAcrossActors (
2729+ decl, isolation, getDeclContext (), None)) {
2730+ if (diagnoseNonSendableTypes (
2731+ component.getComponentType (), getDeclContext (),
2732+ component.getLoc (),
2733+ diag::non_sendable_keypath_access)) {
2734+ diagnosed = true ;
2735+ }
27502736 break ;
27512737 }
2752- LLVM_FALLTHROUGH; // otherwise, it's invalid so diagnose it.
27532738
2754- case ActorIsolationRestriction::ActorSelf: {
2755- auto decl = concDecl.getDecl ();
27562739 ctx.Diags .diagnose (component.getLoc (),
27572740 diag::actor_isolated_keypath_component,
2758- isolation.getKind () ==
2759- ActorIsolationRestriction::CrossActorSelf,
2741+ isolation.isDistributedActor (),
27602742 decl->getDescriptiveKind (), decl->getName ());
27612743 diagnosed = true ;
27622744 break ;
27632745 }
2764- }; // end switch
27652746 }
27662747
27672748 // Captured values in a path component must conform to Sendable.
@@ -4867,12 +4848,12 @@ static bool isThrowsDecl(ConcreteDeclRef declRef) {
48674848}
48684849
48694850// / Determine whether the given value can be accessed across actors
4870- // / without requiring async promotion .
4851+ // / without from normal synchronous code .
48714852// /
48724853// / \param value The value we are checking.
48734854// / \param isolation The actor isolation of the value.
48744855// / \param fromDC The context where we are performing the access.
4875- static bool isAccessibleAcrossActorsWithoutAsyncPromotion (
4856+ static bool isAccessibleAcrossActors (
48764857 ValueDecl *value, const ActorIsolation &isolation,
48774858 const DeclContext *fromDC, Optional<ReferencedActor> actorInstance) {
48784859 switch (value->getKind ()) {
@@ -5024,7 +5005,7 @@ ActorReferenceResult ActorReferenceResult::forReference(
50245005 // At this point, we are accessing the target from outside the actor.
50255006 // First, check whether it is something that can be accessed directly,
50265007 // without any kind of promotion.
5027- if (isAccessibleAcrossActorsWithoutAsyncPromotion (
5008+ if (isAccessibleAcrossActors (
50285009 declRef.getDecl (), declIsolation, fromDC, actorInstance))
50295010 return forEntersActor (declIsolation, None);
50305011
0 commit comments