@@ -1597,6 +1597,10 @@ static void noteGlobalActorOnContext(DeclContext *dc, Type globalActor) {
1597
1597
}
1598
1598
}
1599
1599
1600
+ static bool isAccessibleAcrossActors (
1601
+ ValueDecl *value, const ActorIsolation &isolation,
1602
+ const DeclContext *fromDC, Optional<ReferencedActor> actorInstance);
1603
+
1600
1604
namespace {
1601
1605
// / Check for adherence to the actor isolation rules, emitting errors
1602
1606
// / when actor-isolated declarations are used in an unsafe manner.
@@ -2696,72 +2700,49 @@ namespace {
2696
2700
bool checkKeyPathExpr (KeyPathExpr *keyPath) {
2697
2701
bool diagnosed = false ;
2698
2702
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
-
2719
2703
// check the components of the keypath.
2720
2704
for (const auto &component : keyPath->getComponents ()) {
2721
2705
// The decl referred to by the path component cannot be within an actor.
2722
2706
if (component.hasDeclRef ()) {
2723
2707
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 ;
2738
2715
2739
- case ActorIsolationRestriction::GlobalActor:
2716
+ case ActorIsolation::GlobalActor:
2717
+ case ActorIsolation::GlobalActorUnsafe:
2740
2718
// Disable global actor checking for now.
2741
- if (!ctx.LangOpts .isSwiftVersionAtLeast (6 ))
2719
+ if (isolation.isGlobalActor () &&
2720
+ !ctx.LangOpts .isSwiftVersionAtLeast (6 ))
2742
2721
break ;
2743
2722
2744
- LLVM_FALLTHROUGH; // otherwise, it's invalid so diagnose it.
2723
+ LLVM_FALLTHROUGH;
2745
2724
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
+ }
2750
2736
break ;
2751
2737
}
2752
- LLVM_FALLTHROUGH; // otherwise, it's invalid so diagnose it.
2753
2738
2754
- case ActorIsolationRestriction::ActorSelf: {
2755
- auto decl = concDecl.getDecl ();
2756
2739
ctx.Diags .diagnose (component.getLoc (),
2757
2740
diag::actor_isolated_keypath_component,
2758
- isolation.getKind () ==
2759
- ActorIsolationRestriction::CrossActorSelf,
2741
+ isolation.isDistributedActor (),
2760
2742
decl->getDescriptiveKind (), decl->getName ());
2761
2743
diagnosed = true ;
2762
2744
break ;
2763
2745
}
2764
- }; // end switch
2765
2746
}
2766
2747
2767
2748
// Captured values in a path component must conform to Sendable.
@@ -4867,12 +4848,12 @@ static bool isThrowsDecl(ConcreteDeclRef declRef) {
4867
4848
}
4868
4849
4869
4850
// / Determine whether the given value can be accessed across actors
4870
- // / without requiring async promotion .
4851
+ // / without from normal synchronous code .
4871
4852
// /
4872
4853
// / \param value The value we are checking.
4873
4854
// / \param isolation The actor isolation of the value.
4874
4855
// / \param fromDC The context where we are performing the access.
4875
- static bool isAccessibleAcrossActorsWithoutAsyncPromotion (
4856
+ static bool isAccessibleAcrossActors (
4876
4857
ValueDecl *value, const ActorIsolation &isolation,
4877
4858
const DeclContext *fromDC, Optional<ReferencedActor> actorInstance) {
4878
4859
switch (value->getKind ()) {
@@ -5024,7 +5005,7 @@ ActorReferenceResult ActorReferenceResult::forReference(
5024
5005
// At this point, we are accessing the target from outside the actor.
5025
5006
// First, check whether it is something that can be accessed directly,
5026
5007
// without any kind of promotion.
5027
- if (isAccessibleAcrossActorsWithoutAsyncPromotion (
5008
+ if (isAccessibleAcrossActors (
5028
5009
declRef.getDecl (), declIsolation, fromDC, actorInstance))
5029
5010
return forEntersActor (declIsolation, None);
5030
5011
0 commit comments