@@ -1651,6 +1651,10 @@ static void noteGlobalActorOnContext(DeclContext *dc, Type globalActor) {
16511651 }
16521652}
16531653
1654+ static bool isAccessibleAcrossActors (
1655+ ValueDecl *value, const ActorIsolation &isolation,
1656+ const DeclContext *fromDC, Optional<ReferencedActor> actorInstance);
1657+
16541658namespace {
16551659 // / Check for adherence to the actor isolation rules, emitting errors
16561660 // / when actor-isolated declarations are used in an unsafe manner.
@@ -2758,72 +2762,49 @@ namespace {
27582762 bool checkKeyPathExpr (KeyPathExpr *keyPath) {
27592763 bool diagnosed = false ;
27602764
2761- // returns None if it is not a 'let'-bound var decl. Otherwise,
2762- // the bool indicates whether a diagnostic was emitted.
2763- auto checkLetBoundVarDecl = [&](KeyPathExpr::Component const & component)
2764- -> Optional<bool > {
2765- auto decl = component.getDeclRef ().getDecl ();
2766- if (auto varDecl = dyn_cast<VarDecl>(decl)) {
2767- if (varDecl->isLet ()) {
2768- auto type = component.getComponentType ();
2769- if (shouldDiagnoseExistingDataRaces (getDeclContext ()) &&
2770- diagnoseNonSendableTypes (
2771- type, getDeclContext (), component.getLoc (),
2772- diag::non_sendable_keypath_access))
2773- return true ;
2774-
2775- return false ;
2776- }
2777- }
2778- return None;
2779- };
2780-
27812765 // check the components of the keypath.
27822766 for (const auto &component : keyPath->getComponents ()) {
27832767 // The decl referred to by the path component cannot be within an actor.
27842768 if (component.hasDeclRef ()) {
27852769 auto concDecl = component.getDeclRef ();
2786- auto isolation = ActorIsolationRestriction::forDeclaration (
2787- concDecl, getDeclContext ());
2788-
2789- switch (isolation.getKind ()) {
2790- case ActorIsolationRestriction::Unsafe:
2791- case ActorIsolationRestriction::Unrestricted:
2792- break ; // OK. Does not refer to an actor-isolated member.
2793-
2794- case ActorIsolationRestriction::GlobalActorUnsafe:
2795- // Only check if we're in code that's adopted concurrency features.
2796- if (!shouldDiagnoseExistingDataRaces (getDeclContext ()))
2797- break ; // do not check
2798-
2799- LLVM_FALLTHROUGH; // otherwise, perform checking
2770+ auto decl = concDecl.getDecl ();
2771+ auto isolation = getActorIsolationForReference (
2772+ decl, getDeclContext ());
2773+ switch (isolation) {
2774+ case ActorIsolation::Independent:
2775+ case ActorIsolation::Unspecified:
2776+ break ;
28002777
2801- case ActorIsolationRestriction::GlobalActor:
2778+ case ActorIsolation::GlobalActor:
2779+ case ActorIsolation::GlobalActorUnsafe:
28022780 // Disable global actor checking for now.
2803- if (!ctx.LangOpts .isSwiftVersionAtLeast (6 ))
2781+ if (isolation.isGlobalActor () &&
2782+ !ctx.LangOpts .isSwiftVersionAtLeast (6 ))
28042783 break ;
28052784
2806- LLVM_FALLTHROUGH; // otherwise, it's invalid so diagnose it.
2785+ LLVM_FALLTHROUGH;
28072786
2808- case ActorIsolationRestriction::CrossActorSelf:
2809- // 'let'-bound decls with this isolation are OK, just check them.
2810- if (auto wasLetBound = checkLetBoundVarDecl (component)) {
2811- diagnosed = wasLetBound.getValue ();
2787+ case ActorIsolation::ActorInstance:
2788+ // If this entity is always accessible across actors, just check
2789+ // Sendable.
2790+ if (isAccessibleAcrossActors (
2791+ decl, isolation, getDeclContext (), None)) {
2792+ if (diagnoseNonSendableTypes (
2793+ component.getComponentType (), getDeclContext (),
2794+ component.getLoc (),
2795+ diag::non_sendable_keypath_access)) {
2796+ diagnosed = true ;
2797+ }
28122798 break ;
28132799 }
2814- LLVM_FALLTHROUGH; // otherwise, it's invalid so diagnose it.
28152800
2816- case ActorIsolationRestriction::ActorSelf: {
2817- auto decl = concDecl.getDecl ();
28182801 ctx.Diags .diagnose (component.getLoc (),
28192802 diag::actor_isolated_keypath_component,
2820- isolation.getKind () ==
2821- ActorIsolationRestriction::CrossActorSelf,
2803+ isolation.isDistributedActor (),
28222804 decl->getDescriptiveKind (), decl->getName ());
28232805 diagnosed = true ;
28242806 break ;
28252807 }
2826- }; // end switch
28272808 }
28282809
28292810 // Captured values in a path component must conform to Sendable.
@@ -4937,12 +4918,12 @@ static bool isThrowsDecl(ConcreteDeclRef declRef) {
49374918}
49384919
49394920// / Determine whether the given value can be accessed across actors
4940- // / without requiring async promotion .
4921+ // / without from normal synchronous code .
49414922// /
49424923// / \param value The value we are checking.
49434924// / \param isolation The actor isolation of the value.
49444925// / \param fromDC The context where we are performing the access.
4945- static bool isAccessibleAcrossActorsWithoutAsyncPromotion (
4926+ static bool isAccessibleAcrossActors (
49464927 ValueDecl *value, const ActorIsolation &isolation,
49474928 const DeclContext *fromDC, Optional<ReferencedActor> actorInstance) {
49484929 switch (value->getKind ()) {
@@ -5094,7 +5075,7 @@ ActorReferenceResult ActorReferenceResult::forReference(
50945075 // At this point, we are accessing the target from outside the actor.
50955076 // First, check whether it is something that can be accessed directly,
50965077 // without any kind of promotion.
5097- if (isAccessibleAcrossActorsWithoutAsyncPromotion (
5078+ if (isAccessibleAcrossActors (
50985079 declRef.getDecl (), declIsolation, fromDC, actorInstance))
50995080 return forEntersActor (declIsolation, None);
51005081
0 commit comments