@@ -1447,7 +1447,7 @@ static bool memberAccessHasSpecialPermissionInSwift5(DeclContext const *refCxt,
1447
1447
member->getDescriptiveKind (),
1448
1448
member->getName (),
1449
1449
useKindInt,
1450
- baseActor.kind ,
1450
+ baseActor.kind + 1 ,
1451
1451
baseActor.globalActor ,
1452
1452
getActorIsolation (const_cast <ValueDecl *>(member)))
1453
1453
.warnUntilSwiftVersion (6 );
@@ -1881,16 +1881,23 @@ namespace {
1881
1881
recordMutableVarParent (load, load->getSubExpr ());
1882
1882
1883
1883
if (auto lookup = dyn_cast<LookupExpr>(expr)) {
1884
- checkMemberReference (lookup->getBase (), lookup->getMember (),
1884
+ checkReference (lookup->getBase (), lookup->getMember (),
1885
1885
lookup->getLoc (),
1886
1886
/* partialApply*/ None,
1887
1887
lookup);
1888
1888
return { true , expr };
1889
1889
}
1890
1890
1891
1891
if (auto declRef = dyn_cast<DeclRefExpr>(expr)) {
1892
- checkNonMemberReference (
1893
- declRef->getDeclRef (), declRef->getLoc (), declRef);
1892
+ auto valueRef = declRef->getDeclRef ();
1893
+ auto value = valueRef.getDecl ();
1894
+ auto loc = declRef->getLoc ();
1895
+
1896
+ // FIXME: Should this be subsumed in reference checking?
1897
+ if (value->isLocalCapture ())
1898
+ checkLocalCapture (valueRef, loc, declRef);
1899
+ else
1900
+ checkReference (nullptr , valueRef, loc, None, declRef);
1894
1901
return { true , expr };
1895
1902
}
1896
1903
@@ -1907,7 +1914,7 @@ namespace {
1907
1914
if (auto memberRef = findMemberReference (partialApply->fn )) {
1908
1915
// NOTE: partially-applied thunks are never annotated as
1909
1916
// implicitly async, regardless of whether they are escaping.
1910
- checkMemberReference (
1917
+ checkReference (
1911
1918
partialApply->base , memberRef->first , memberRef->second ,
1912
1919
partialApply);
1913
1920
@@ -1926,7 +1933,7 @@ namespace {
1926
1933
if (auto call = dyn_cast<SelfApplyExpr>(expr)) {
1927
1934
Expr *fn = call->getFn ()->getValueProvidingExpr ();
1928
1935
if (auto memberRef = findMemberReference (fn)) {
1929
- checkMemberReference (
1936
+ checkReference (
1930
1937
call->getBase (), memberRef->first , memberRef->second ,
1931
1938
/* partialApply=*/ None, call);
1932
1939
@@ -2215,7 +2222,15 @@ namespace {
2215
2222
if (!var || var->isLet ())
2216
2223
return false ;
2217
2224
2218
- if (!var->getDeclContext ()->isModuleScopeContext () && !var->isStatic ())
2225
+ if (!var->getDeclContext ()->isModuleScopeContext () &&
2226
+ !(var->getDeclContext ()->isTypeContext () && !var->isInstanceMember ()))
2227
+ return false ;
2228
+
2229
+ if (!var->hasStorage ())
2230
+ return false ;
2231
+
2232
+ // If it's actor-isolated, it's already been dealt with.
2233
+ if (getActorIsolation (value).isActorIsolated ())
2219
2234
return false ;
2220
2235
2221
2236
ctx.Diags .diagnose (
@@ -2604,97 +2619,6 @@ namespace {
2604
2619
return false ;
2605
2620
}
2606
2621
2607
- // / Check a reference to an entity within a global actor.
2608
- bool checkGlobalActorReference (
2609
- ConcreteDeclRef valueRef, SourceLoc loc, Type globalActor,
2610
- bool isCrossActor,
2611
- Expr *context) {
2612
- ValueDecl *value = valueRef.getDecl ();
2613
- auto declContext = const_cast <DeclContext *>(getDeclContext ());
2614
-
2615
- // Check whether we are within the same isolation context, in which
2616
- // case there is nothing further to check,
2617
- auto contextIsolation = getInnermostIsolatedContext (declContext);
2618
- if (contextIsolation.isGlobalActor () &&
2619
- contextIsolation.getGlobalActor ()->isEqual (globalActor)) {
2620
- return false ;
2621
- }
2622
-
2623
- // A cross-actor access requires types to be concurrent-safe.
2624
- if (isCrossActor) {
2625
- return diagnoseNonSendableTypesInReference (
2626
- valueRef, getDeclContext (), loc,
2627
- SendableCheckReason::CrossActor);
2628
- }
2629
-
2630
- // Call is implicitly asynchronous.
2631
- auto result = tryMarkImplicitlyAsync (
2632
- loc, valueRef, context,
2633
- ImplicitActorHopTarget::forGlobalActor (globalActor),
2634
- /* FIXME if we get global distributed actors*/ false );
2635
- if (result == AsyncMarkingResult::FoundAsync)
2636
- return false ;
2637
-
2638
- // Diagnose failures.
2639
- switch (contextIsolation) {
2640
- case ActorIsolation::ActorInstance: {
2641
- auto useKind = static_cast <unsigned >(
2642
- kindOfUsage (value, context).getValueOr (VarRefUseEnv::Read));
2643
-
2644
- ctx.Diags .diagnose (loc, diag::global_actor_from_instance_actor_context,
2645
- value->getDescriptiveKind (), value->getName (),
2646
- globalActor, contextIsolation.getActor ()->getName (),
2647
- useKind, result == AsyncMarkingResult::SyncContext);
2648
- noteIsolatedActorMember (value, context);
2649
- return true ;
2650
- }
2651
-
2652
- case ActorIsolation::GlobalActor:
2653
- case ActorIsolation::GlobalActorUnsafe: {
2654
- auto useKind = static_cast <unsigned >(
2655
- kindOfUsage (value, context).getValueOr (VarRefUseEnv::Read));
2656
-
2657
- // Otherwise, this is a problematic global actor decl reference.
2658
- ctx.Diags .diagnose (
2659
- loc, diag::global_actor_from_other_global_actor_context,
2660
- value->getDescriptiveKind (), value->getName (), globalActor,
2661
- contextIsolation.getGlobalActor (), useKind,
2662
- result == AsyncMarkingResult::SyncContext);
2663
- noteIsolatedActorMember (value, context);
2664
- return true ;
2665
- }
2666
-
2667
- case ActorIsolation::Independent: {
2668
- auto useKind = static_cast <unsigned >(
2669
- kindOfUsage (value, context).getValueOr (VarRefUseEnv::Read));
2670
-
2671
- ctx.Diags .diagnose (loc, diag::global_actor_from_nonactor_context,
2672
- value->getDescriptiveKind (), value->getName (),
2673
- globalActor,
2674
- /* actorIndependent=*/ true , useKind,
2675
- result == AsyncMarkingResult::SyncContext);
2676
- noteIsolatedActorMember (value, context);
2677
- return true ;
2678
- }
2679
-
2680
- case ActorIsolation::Unspecified: {
2681
- // Diagnose the reference.
2682
- auto useKind = static_cast <unsigned >(
2683
- kindOfUsage (value, context).getValueOr (VarRefUseEnv::Read));
2684
- ctx.Diags .diagnose (
2685
- loc, diag::global_actor_from_nonactor_context,
2686
- value->getDescriptiveKind (), value->getName (), globalActor,
2687
- /* actorIndependent=*/ false , useKind,
2688
- result == AsyncMarkingResult::SyncContext);
2689
- noteGlobalActorOnContext (declContext, globalActor);
2690
- noteIsolatedActorMember (value, context);
2691
-
2692
- return true ;
2693
- } // end Unspecified case
2694
- } // end switch
2695
- llvm_unreachable (" unhandled actor isolation kind!" );
2696
- }
2697
-
2698
2622
// / Find the innermost context in which this declaration was explicitly
2699
2623
// / captured.
2700
2624
const DeclContext *findCapturedDeclContext (ValueDecl *value) {
@@ -2874,65 +2798,38 @@ namespace {
2874
2798
return diagnosed;
2875
2799
}
2876
2800
2877
- // / Check a reference to a local or global.
2878
- bool checkNonMemberReference (
2879
- ConcreteDeclRef valueRef, SourceLoc loc, DeclRefExpr *declRefExpr) {
2880
- if (!valueRef)
2881
- return false ;
2882
-
2883
- auto value = valueRef.getDecl ();
2884
-
2885
- if (value->isLocalCapture ())
2886
- return checkLocalCapture (valueRef, loc, declRefExpr);
2887
-
2888
- switch (auto isolation =
2889
- ActorIsolationRestriction::forDeclaration (
2890
- valueRef, getDeclContext ())) {
2891
- case ActorIsolationRestriction::Unrestricted:
2892
- return false ;
2893
-
2894
- case ActorIsolationRestriction::CrossActorSelf:
2895
- case ActorIsolationRestriction::ActorSelf:
2896
- llvm_unreachable (" non-member reference into an actor" );
2897
-
2898
- case ActorIsolationRestriction::GlobalActorUnsafe:
2899
- // Only complain if we're in code that's adopted concurrency features.
2900
- if (!shouldDiagnoseExistingDataRaces (getDeclContext ()))
2901
- return false ;
2902
-
2903
- LLVM_FALLTHROUGH;
2904
-
2905
- case ActorIsolationRestriction::GlobalActor:
2906
- return checkGlobalActorReference (
2907
- valueRef, loc, isolation.getGlobalActor (), isolation.isCrossActor ,
2908
- declRefExpr);
2909
-
2910
- case ActorIsolationRestriction::Unsafe:
2911
- return diagnoseReferenceToUnsafeGlobal (value, loc);
2912
- }
2913
- llvm_unreachable (" unhandled actor isolation kind!" );
2914
- }
2915
-
2916
- // / Check a reference with the given base expression to the given member.
2917
- // / Returns true iff the member reference refers to actor-isolated state
2918
- // / in an invalid or unsafe way such that a diagnostic was emitted.
2919
- bool checkMemberReference (
2920
- Expr *base, ConcreteDeclRef memberRef, SourceLoc memberLoc,
2801
+ // / Check a reference to the given declaration.
2802
+ // /
2803
+ // / \param base For a reference to a member, the base expression. May be
2804
+ // / nullptr for non-member referenced.
2805
+ // /
2806
+ // / \returns true if the reference is invalid, in which case a diagnostic
2807
+ // / has already been emitted.
2808
+ bool checkReference (
2809
+ Expr *base, ConcreteDeclRef declRef, SourceLoc loc,
2921
2810
Optional<PartialApplyThunkInfo> partialApply = None,
2922
2811
Expr *context = nullptr ) {
2923
- if (!base || !memberRef )
2812
+ if (!declRef )
2924
2813
return false ;
2925
2814
2926
- auto member = memberRef.getDecl ();
2927
- auto isolatedActor = getIsolatedActor (base);
2815
+ auto decl = declRef.getDecl ();
2816
+ Optional<ReferencedActor> isolatedActor;
2817
+ if (base)
2818
+ isolatedActor.emplace (getIsolatedActor (base));
2928
2819
auto result = ActorReferenceResult::forReference (
2929
- memberRef, memberLoc , getDeclContext (),
2930
- kindOfUsage (member , context), isolatedActor);
2820
+ declRef, loc , getDeclContext (),
2821
+ kindOfUsage (decl , context), isolatedActor);
2931
2822
switch (result) {
2932
2823
case ActorReferenceResult::SameConcurrencyDomain:
2824
+ if (diagnoseReferenceToUnsafeGlobal (decl, loc))
2825
+ return true ;
2826
+
2933
2827
return false ;
2934
2828
2935
2829
case ActorReferenceResult::ExitsActorToNonisolated:
2830
+ if (diagnoseReferenceToUnsafeGlobal (decl, loc))
2831
+ return true ;
2832
+
2936
2833
// FIXME: SE-0338 would trigger Sendable checks here.
2937
2834
return false ;
2938
2835
@@ -2949,24 +2846,24 @@ namespace {
2949
2846
2950
2847
// A call to a global-actor-isolated function is diagnosed elsewhere.
2951
2848
if (!partialApply && result.isolation .isGlobalActor () &&
2952
- isa<AbstractFunctionDecl>(member ))
2849
+ isa<AbstractFunctionDecl>(decl ))
2953
2850
return false ;
2954
2851
2955
2852
// An escaping partial application of something that is part of
2956
2853
// the actor's isolated state is never permitted.
2957
- if (partialApply && partialApply->isEscaping && !isAsyncDecl (memberRef )) {
2854
+ if (partialApply && partialApply->isEscaping && !isAsyncDecl (declRef )) {
2958
2855
ctx.Diags .diagnose (
2959
- memberLoc , diag::actor_isolated_partial_apply,
2960
- member ->getDescriptiveKind (),
2961
- member ->getName ());
2856
+ loc , diag::actor_isolated_partial_apply,
2857
+ decl ->getDescriptiveKind (),
2858
+ decl ->getName ());
2962
2859
return true ;
2963
2860
}
2964
2861
2965
2862
// If we do not need any async/throws/distributed checks, just perform
2966
2863
// Sendable checking and we're done.
2967
2864
if (!result.options ) {
2968
2865
return diagnoseNonSendableTypesInReference (
2969
- memberRef , getDeclContext (), memberLoc ,
2866
+ declRef , getDeclContext (), loc ,
2970
2867
SendableCheckReason::CrossActor);
2971
2868
}
2972
2869
@@ -2980,7 +2877,7 @@ namespace {
2980
2877
result.isolation .getGlobalActor ())
2981
2878
: ImplicitActorHopTarget::forInstanceSelf ();
2982
2879
auto implicitAsyncResult = tryMarkImplicitlyAsync (
2983
- memberLoc, memberRef , context, target, isDistributed);
2880
+ loc, declRef , context, target, isDistributed);
2984
2881
switch (implicitAsyncResult) {
2985
2882
case AsyncMarkingResult::FoundAsync:
2986
2883
// Success! We're done.
@@ -2995,18 +2892,44 @@ namespace {
2995
2892
case AsyncMarkingResult::NotFound:
2996
2893
// Complain about access outside of the isolation domain.
2997
2894
auto useKind = static_cast <unsigned >(
2998
- kindOfUsage (member, context).getValueOr (VarRefUseEnv::Read));
2895
+ kindOfUsage (decl, context).getValueOr (VarRefUseEnv::Read));
2896
+
2897
+ ReferencedActor::Kind refKind;
2898
+ Type refGlobalActor;
2899
+ if (isolatedActor) {
2900
+ refKind = isolatedActor->kind ;
2901
+ refGlobalActor = isolatedActor->globalActor ;
2902
+ } else {
2903
+ auto contextIsolation = getInnermostIsolatedContext (getDeclContext ());
2904
+ switch (contextIsolation) {
2905
+ case ActorIsolation::ActorInstance:
2906
+ refKind = ReferencedActor::Isolated;
2907
+ break ;
2908
+
2909
+ case ActorIsolation::GlobalActor:
2910
+ case ActorIsolation::GlobalActorUnsafe:
2911
+ refGlobalActor = contextIsolation.getGlobalActor ();
2912
+ refKind = isMainActor (refGlobalActor)
2913
+ ? ReferencedActor::MainActor
2914
+ : ReferencedActor::GlobalActor;
2915
+ break ;
2916
+
2917
+ case ActorIsolation::Unspecified:
2918
+ case ActorIsolation::Independent:
2919
+ refKind = ReferencedActor::NonIsolatedContext;
2920
+ break ;
2921
+ }
2922
+ }
2999
2923
3000
2924
ctx.Diags .diagnose (
3001
- memberLoc , diag::actor_isolated_non_self_reference,
3002
- member ->getDescriptiveKind (),
3003
- member ->getName (),
2925
+ loc , diag::actor_isolated_non_self_reference,
2926
+ decl ->getDescriptiveKind (),
2927
+ decl ->getName (),
3004
2928
useKind,
3005
- isolatedActor.kind ,
3006
- isolatedActor.globalActor ,
2929
+ refKind + 1 , refGlobalActor,
3007
2930
result.isolation );
3008
2931
3009
- noteIsolatedActorMember (member , context);
2932
+ noteIsolatedActorMember (decl , context);
3010
2933
3011
2934
if (result.isolation .isGlobalActor ()) {
3012
2935
noteGlobalActorOnContext (
0 commit comments