@@ -1501,7 +1501,7 @@ static bool memberAccessHasSpecialPermissionInSwift5(DeclContext const *refCxt,
1501
1501
member->getDescriptiveKind (),
1502
1502
member->getName (),
1503
1503
useKindInt,
1504
- baseActor.kind ,
1504
+ baseActor.kind + 1 ,
1505
1505
baseActor.globalActor ,
1506
1506
getActorIsolation (const_cast <ValueDecl *>(member)))
1507
1507
.warnUntilSwiftVersion (6 );
@@ -1935,16 +1935,23 @@ namespace {
1935
1935
recordMutableVarParent (load, load->getSubExpr ());
1936
1936
1937
1937
if (auto lookup = dyn_cast<LookupExpr>(expr)) {
1938
- checkMemberReference (lookup->getBase (), lookup->getMember (),
1938
+ checkReference (lookup->getBase (), lookup->getMember (),
1939
1939
lookup->getLoc (),
1940
1940
/* partialApply*/ None,
1941
1941
lookup);
1942
1942
return { true , expr };
1943
1943
}
1944
1944
1945
1945
if (auto declRef = dyn_cast<DeclRefExpr>(expr)) {
1946
- checkNonMemberReference (
1947
- declRef->getDeclRef (), declRef->getLoc (), declRef);
1946
+ auto valueRef = declRef->getDeclRef ();
1947
+ auto value = valueRef.getDecl ();
1948
+ auto loc = declRef->getLoc ();
1949
+
1950
+ // FIXME: Should this be subsumed in reference checking?
1951
+ if (value->isLocalCapture ())
1952
+ checkLocalCapture (valueRef, loc, declRef);
1953
+ else
1954
+ checkReference (nullptr , valueRef, loc, None, declRef);
1948
1955
return { true , expr };
1949
1956
}
1950
1957
@@ -1961,7 +1968,7 @@ namespace {
1961
1968
if (auto memberRef = findMemberReference (partialApply->fn )) {
1962
1969
// NOTE: partially-applied thunks are never annotated as
1963
1970
// implicitly async, regardless of whether they are escaping.
1964
- checkMemberReference (
1971
+ checkReference (
1965
1972
partialApply->base , memberRef->first , memberRef->second ,
1966
1973
partialApply);
1967
1974
@@ -1980,7 +1987,7 @@ namespace {
1980
1987
if (auto call = dyn_cast<SelfApplyExpr>(expr)) {
1981
1988
Expr *fn = call->getFn ()->getValueProvidingExpr ();
1982
1989
if (auto memberRef = findMemberReference (fn)) {
1983
- checkMemberReference (
1990
+ checkReference (
1984
1991
call->getBase (), memberRef->first , memberRef->second ,
1985
1992
/* partialApply=*/ None, call);
1986
1993
@@ -2276,7 +2283,15 @@ namespace {
2276
2283
if (!var || var->isLet ())
2277
2284
return false ;
2278
2285
2279
- if (!var->getDeclContext ()->isModuleScopeContext () && !var->isStatic ())
2286
+ if (!var->getDeclContext ()->isModuleScopeContext () &&
2287
+ !(var->getDeclContext ()->isTypeContext () && !var->isInstanceMember ()))
2288
+ return false ;
2289
+
2290
+ if (!var->hasStorage ())
2291
+ return false ;
2292
+
2293
+ // If it's actor-isolated, it's already been dealt with.
2294
+ if (getActorIsolation (value).isActorIsolated ())
2280
2295
return false ;
2281
2296
2282
2297
ctx.Diags .diagnose (
@@ -2665,97 +2680,6 @@ namespace {
2665
2680
return false ;
2666
2681
}
2667
2682
2668
- // / Check a reference to an entity within a global actor.
2669
- bool checkGlobalActorReference (
2670
- ConcreteDeclRef valueRef, SourceLoc loc, Type globalActor,
2671
- bool isCrossActor,
2672
- Expr *context) {
2673
- ValueDecl *value = valueRef.getDecl ();
2674
- auto declContext = const_cast <DeclContext *>(getDeclContext ());
2675
-
2676
- // Check whether we are within the same isolation context, in which
2677
- // case there is nothing further to check,
2678
- auto contextIsolation = getInnermostIsolatedContext (declContext);
2679
- if (contextIsolation.isGlobalActor () &&
2680
- contextIsolation.getGlobalActor ()->isEqual (globalActor)) {
2681
- return false ;
2682
- }
2683
-
2684
- // A cross-actor access requires types to be concurrent-safe.
2685
- if (isCrossActor) {
2686
- return diagnoseNonSendableTypesInReference (
2687
- valueRef, getDeclContext (), loc,
2688
- SendableCheckReason::CrossActor);
2689
- }
2690
-
2691
- // Call is implicitly asynchronous.
2692
- auto result = tryMarkImplicitlyAsync (
2693
- loc, valueRef, context,
2694
- ImplicitActorHopTarget::forGlobalActor (globalActor),
2695
- /* FIXME if we get global distributed actors*/ false );
2696
- if (result == AsyncMarkingResult::FoundAsync)
2697
- return false ;
2698
-
2699
- // Diagnose failures.
2700
- switch (contextIsolation) {
2701
- case ActorIsolation::ActorInstance: {
2702
- auto useKind = static_cast <unsigned >(
2703
- kindOfUsage (value, context).getValueOr (VarRefUseEnv::Read));
2704
-
2705
- ctx.Diags .diagnose (loc, diag::global_actor_from_instance_actor_context,
2706
- value->getDescriptiveKind (), value->getName (),
2707
- globalActor, contextIsolation.getActor ()->getName (),
2708
- useKind, result == AsyncMarkingResult::SyncContext);
2709
- noteIsolatedActorMember (value, context);
2710
- return true ;
2711
- }
2712
-
2713
- case ActorIsolation::GlobalActor:
2714
- case ActorIsolation::GlobalActorUnsafe: {
2715
- auto useKind = static_cast <unsigned >(
2716
- kindOfUsage (value, context).getValueOr (VarRefUseEnv::Read));
2717
-
2718
- // Otherwise, this is a problematic global actor decl reference.
2719
- ctx.Diags .diagnose (
2720
- loc, diag::global_actor_from_other_global_actor_context,
2721
- value->getDescriptiveKind (), value->getName (), globalActor,
2722
- contextIsolation.getGlobalActor (), useKind,
2723
- result == AsyncMarkingResult::SyncContext);
2724
- noteIsolatedActorMember (value, context);
2725
- return true ;
2726
- }
2727
-
2728
- case ActorIsolation::Independent: {
2729
- auto useKind = static_cast <unsigned >(
2730
- kindOfUsage (value, context).getValueOr (VarRefUseEnv::Read));
2731
-
2732
- ctx.Diags .diagnose (loc, diag::global_actor_from_nonactor_context,
2733
- value->getDescriptiveKind (), value->getName (),
2734
- globalActor,
2735
- /* actorIndependent=*/ true , useKind,
2736
- result == AsyncMarkingResult::SyncContext);
2737
- noteIsolatedActorMember (value, context);
2738
- return true ;
2739
- }
2740
-
2741
- case ActorIsolation::Unspecified: {
2742
- // Diagnose the reference.
2743
- auto useKind = static_cast <unsigned >(
2744
- kindOfUsage (value, context).getValueOr (VarRefUseEnv::Read));
2745
- ctx.Diags .diagnose (
2746
- loc, diag::global_actor_from_nonactor_context,
2747
- value->getDescriptiveKind (), value->getName (), globalActor,
2748
- /* actorIndependent=*/ false , useKind,
2749
- result == AsyncMarkingResult::SyncContext);
2750
- noteGlobalActorOnContext (declContext, globalActor);
2751
- noteIsolatedActorMember (value, context);
2752
-
2753
- return true ;
2754
- } // end Unspecified case
2755
- } // end switch
2756
- llvm_unreachable (" unhandled actor isolation kind!" );
2757
- }
2758
-
2759
2683
// / Find the innermost context in which this declaration was explicitly
2760
2684
// / captured.
2761
2685
const DeclContext *findCapturedDeclContext (ValueDecl *value) {
@@ -2936,65 +2860,38 @@ namespace {
2936
2860
return diagnosed;
2937
2861
}
2938
2862
2939
- // / Check a reference to a local or global.
2940
- bool checkNonMemberReference (
2941
- ConcreteDeclRef valueRef, SourceLoc loc, DeclRefExpr *declRefExpr) {
2942
- if (!valueRef)
2943
- return false ;
2944
-
2945
- auto value = valueRef.getDecl ();
2946
-
2947
- if (value->isLocalCapture ())
2948
- return checkLocalCapture (valueRef, loc, declRefExpr);
2949
-
2950
- switch (auto isolation =
2951
- ActorIsolationRestriction::forDeclaration (
2952
- valueRef, getDeclContext ())) {
2953
- case ActorIsolationRestriction::Unrestricted:
2954
- return false ;
2955
-
2956
- case ActorIsolationRestriction::CrossActorSelf:
2957
- case ActorIsolationRestriction::ActorSelf:
2958
- llvm_unreachable (" non-member reference into an actor" );
2959
-
2960
- case ActorIsolationRestriction::GlobalActorUnsafe:
2961
- // Only complain if we're in code that's adopted concurrency features.
2962
- if (!shouldDiagnoseExistingDataRaces (getDeclContext ()))
2963
- return false ;
2964
-
2965
- LLVM_FALLTHROUGH;
2966
-
2967
- case ActorIsolationRestriction::GlobalActor:
2968
- return checkGlobalActorReference (
2969
- valueRef, loc, isolation.getGlobalActor (), isolation.isCrossActor ,
2970
- declRefExpr);
2971
-
2972
- case ActorIsolationRestriction::Unsafe:
2973
- return diagnoseReferenceToUnsafeGlobal (value, loc);
2974
- }
2975
- llvm_unreachable (" unhandled actor isolation kind!" );
2976
- }
2977
-
2978
- // / Check a reference with the given base expression to the given member.
2979
- // / Returns true iff the member reference refers to actor-isolated state
2980
- // / in an invalid or unsafe way such that a diagnostic was emitted.
2981
- bool checkMemberReference (
2982
- Expr *base, ConcreteDeclRef memberRef, SourceLoc memberLoc,
2863
+ // / Check a reference to the given declaration.
2864
+ // /
2865
+ // / \param base For a reference to a member, the base expression. May be
2866
+ // / nullptr for non-member referenced.
2867
+ // /
2868
+ // / \returns true if the reference is invalid, in which case a diagnostic
2869
+ // / has already been emitted.
2870
+ bool checkReference (
2871
+ Expr *base, ConcreteDeclRef declRef, SourceLoc loc,
2983
2872
Optional<PartialApplyThunkInfo> partialApply = None,
2984
2873
Expr *context = nullptr ) {
2985
- if (!base || !memberRef )
2874
+ if (!declRef )
2986
2875
return false ;
2987
2876
2988
- auto member = memberRef.getDecl ();
2989
- auto isolatedActor = getIsolatedActor (base);
2877
+ auto decl = declRef.getDecl ();
2878
+ Optional<ReferencedActor> isolatedActor;
2879
+ if (base)
2880
+ isolatedActor.emplace (getIsolatedActor (base));
2990
2881
auto result = ActorReferenceResult::forReference (
2991
- memberRef, memberLoc , getDeclContext (),
2992
- kindOfUsage (member , context), isolatedActor);
2882
+ declRef, loc , getDeclContext (),
2883
+ kindOfUsage (decl , context), isolatedActor);
2993
2884
switch (result) {
2994
2885
case ActorReferenceResult::SameConcurrencyDomain:
2886
+ if (diagnoseReferenceToUnsafeGlobal (decl, loc))
2887
+ return true ;
2888
+
2995
2889
return false ;
2996
2890
2997
2891
case ActorReferenceResult::ExitsActorToNonisolated:
2892
+ if (diagnoseReferenceToUnsafeGlobal (decl, loc))
2893
+ return true ;
2894
+
2998
2895
// FIXME: SE-0338 would trigger Sendable checks here.
2999
2896
return false ;
3000
2897
@@ -3011,24 +2908,24 @@ namespace {
3011
2908
3012
2909
// A call to a global-actor-isolated function is diagnosed elsewhere.
3013
2910
if (!partialApply && result.isolation .isGlobalActor () &&
3014
- isa<AbstractFunctionDecl>(member ))
2911
+ isa<AbstractFunctionDecl>(decl ))
3015
2912
return false ;
3016
2913
3017
2914
// An escaping partial application of something that is part of
3018
2915
// the actor's isolated state is never permitted.
3019
- if (partialApply && partialApply->isEscaping && !isAsyncDecl (memberRef )) {
2916
+ if (partialApply && partialApply->isEscaping && !isAsyncDecl (declRef )) {
3020
2917
ctx.Diags .diagnose (
3021
- memberLoc , diag::actor_isolated_partial_apply,
3022
- member ->getDescriptiveKind (),
3023
- member ->getName ());
2918
+ loc , diag::actor_isolated_partial_apply,
2919
+ decl ->getDescriptiveKind (),
2920
+ decl ->getName ());
3024
2921
return true ;
3025
2922
}
3026
2923
3027
2924
// If we do not need any async/throws/distributed checks, just perform
3028
2925
// Sendable checking and we're done.
3029
2926
if (!result.options ) {
3030
2927
return diagnoseNonSendableTypesInReference (
3031
- memberRef , getDeclContext (), memberLoc ,
2928
+ declRef , getDeclContext (), loc ,
3032
2929
SendableCheckReason::CrossActor);
3033
2930
}
3034
2931
@@ -3042,7 +2939,7 @@ namespace {
3042
2939
result.isolation .getGlobalActor ())
3043
2940
: ImplicitActorHopTarget::forInstanceSelf ();
3044
2941
auto implicitAsyncResult = tryMarkImplicitlyAsync (
3045
- memberLoc, memberRef , context, target, isDistributed);
2942
+ loc, declRef , context, target, isDistributed);
3046
2943
switch (implicitAsyncResult) {
3047
2944
case AsyncMarkingResult::FoundAsync:
3048
2945
// Success! We're done.
@@ -3057,18 +2954,44 @@ namespace {
3057
2954
case AsyncMarkingResult::NotFound:
3058
2955
// Complain about access outside of the isolation domain.
3059
2956
auto useKind = static_cast <unsigned >(
3060
- kindOfUsage (member, context).getValueOr (VarRefUseEnv::Read));
2957
+ kindOfUsage (decl, context).getValueOr (VarRefUseEnv::Read));
2958
+
2959
+ ReferencedActor::Kind refKind;
2960
+ Type refGlobalActor;
2961
+ if (isolatedActor) {
2962
+ refKind = isolatedActor->kind ;
2963
+ refGlobalActor = isolatedActor->globalActor ;
2964
+ } else {
2965
+ auto contextIsolation = getInnermostIsolatedContext (getDeclContext ());
2966
+ switch (contextIsolation) {
2967
+ case ActorIsolation::ActorInstance:
2968
+ refKind = ReferencedActor::Isolated;
2969
+ break ;
2970
+
2971
+ case ActorIsolation::GlobalActor:
2972
+ case ActorIsolation::GlobalActorUnsafe:
2973
+ refGlobalActor = contextIsolation.getGlobalActor ();
2974
+ refKind = isMainActor (refGlobalActor)
2975
+ ? ReferencedActor::MainActor
2976
+ : ReferencedActor::GlobalActor;
2977
+ break ;
2978
+
2979
+ case ActorIsolation::Unspecified:
2980
+ case ActorIsolation::Independent:
2981
+ refKind = ReferencedActor::NonIsolatedContext;
2982
+ break ;
2983
+ }
2984
+ }
3061
2985
3062
2986
ctx.Diags .diagnose (
3063
- memberLoc , diag::actor_isolated_non_self_reference,
3064
- member ->getDescriptiveKind (),
3065
- member ->getName (),
2987
+ loc , diag::actor_isolated_non_self_reference,
2988
+ decl ->getDescriptiveKind (),
2989
+ decl ->getName (),
3066
2990
useKind,
3067
- isolatedActor.kind ,
3068
- isolatedActor.globalActor ,
2991
+ refKind + 1 , refGlobalActor,
3069
2992
result.isolation );
3070
2993
3071
- noteIsolatedActorMember (member , context);
2994
+ noteIsolatedActorMember (decl , context);
3072
2995
3073
2996
if (result.isolation .isGlobalActor ()) {
3074
2997
noteGlobalActorOnContext (
0 commit comments