@@ -1651,6 +1651,10 @@ static void noteGlobalActorOnContext(DeclContext *dc, Type globalActor) {
1651
1651
}
1652
1652
}
1653
1653
1654
+ static bool isAccessibleAcrossActors (
1655
+ ValueDecl *value, const ActorIsolation &isolation,
1656
+ const DeclContext *fromDC, Optional<ReferencedActor> actorInstance);
1657
+
1654
1658
namespace {
1655
1659
// / Check for adherence to the actor isolation rules, emitting errors
1656
1660
// / when actor-isolated declarations are used in an unsafe manner.
@@ -2758,72 +2762,49 @@ namespace {
2758
2762
bool checkKeyPathExpr (KeyPathExpr *keyPath) {
2759
2763
bool diagnosed = false ;
2760
2764
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
-
2781
2765
// check the components of the keypath.
2782
2766
for (const auto &component : keyPath->getComponents ()) {
2783
2767
// The decl referred to by the path component cannot be within an actor.
2784
2768
if (component.hasDeclRef ()) {
2785
2769
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 ;
2800
2777
2801
- case ActorIsolationRestriction::GlobalActor:
2778
+ case ActorIsolation::GlobalActor:
2779
+ case ActorIsolation::GlobalActorUnsafe:
2802
2780
// Disable global actor checking for now.
2803
- if (!ctx.LangOpts .isSwiftVersionAtLeast (6 ))
2781
+ if (isolation.isGlobalActor () &&
2782
+ !ctx.LangOpts .isSwiftVersionAtLeast (6 ))
2804
2783
break ;
2805
2784
2806
- LLVM_FALLTHROUGH; // otherwise, it's invalid so diagnose it.
2785
+ LLVM_FALLTHROUGH;
2807
2786
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
+ }
2812
2798
break ;
2813
2799
}
2814
- LLVM_FALLTHROUGH; // otherwise, it's invalid so diagnose it.
2815
2800
2816
- case ActorIsolationRestriction::ActorSelf: {
2817
- auto decl = concDecl.getDecl ();
2818
2801
ctx.Diags .diagnose (component.getLoc (),
2819
2802
diag::actor_isolated_keypath_component,
2820
- isolation.getKind () ==
2821
- ActorIsolationRestriction::CrossActorSelf,
2803
+ isolation.isDistributedActor (),
2822
2804
decl->getDescriptiveKind (), decl->getName ());
2823
2805
diagnosed = true ;
2824
2806
break ;
2825
2807
}
2826
- }; // end switch
2827
2808
}
2828
2809
2829
2810
// Captured values in a path component must conform to Sendable.
@@ -4937,12 +4918,12 @@ static bool isThrowsDecl(ConcreteDeclRef declRef) {
4937
4918
}
4938
4919
4939
4920
// / Determine whether the given value can be accessed across actors
4940
- // / without requiring async promotion .
4921
+ // / without from normal synchronous code .
4941
4922
// /
4942
4923
// / \param value The value we are checking.
4943
4924
// / \param isolation The actor isolation of the value.
4944
4925
// / \param fromDC The context where we are performing the access.
4945
- static bool isAccessibleAcrossActorsWithoutAsyncPromotion (
4926
+ static bool isAccessibleAcrossActors (
4946
4927
ValueDecl *value, const ActorIsolation &isolation,
4947
4928
const DeclContext *fromDC, Optional<ReferencedActor> actorInstance) {
4948
4929
switch (value->getKind ()) {
@@ -5094,7 +5075,7 @@ ActorReferenceResult ActorReferenceResult::forReference(
5094
5075
// At this point, we are accessing the target from outside the actor.
5095
5076
// First, check whether it is something that can be accessed directly,
5096
5077
// without any kind of promotion.
5097
- if (isAccessibleAcrossActorsWithoutAsyncPromotion (
5078
+ if (isAccessibleAcrossActors (
5098
5079
declRef.getDecl (), declIsolation, fromDC, actorInstance))
5099
5080
return forEntersActor (declIsolation, None);
5100
5081
0 commit comments