@@ -406,14 +406,16 @@ bool IsDefaultActorRequest::evaluate(
406
406
}
407
407
408
408
bool IsDistributedActorRequest::evaluate (
409
- Evaluator &evaluator, ClassDecl *classDecl ) const {
410
- // If concurrency is not enabled, we don't have actors.
411
- auto distributedAttr = classDecl ->getAttrs ()
412
- .getAttribute <DistributedActorAttr>();
409
+ Evaluator &evaluator, NominalTypeDecl *nominal ) const {
410
+ if ( auto actor = dyn_cast<ClassDecl>(nominal)) {
411
+ auto distributedAttr = nominal ->getAttrs ()
412
+ .getAttribute <DistributedActorAttr>();
413
413
414
- // NOTE: that we DO NOT infer distributed even if the parent class was distributed.
414
+ return distributedAttr != nullptr ;
415
+ }
415
416
416
- return distributedAttr != nullptr ;
417
+ // TODO: also check for protocols conforming to DistributedActor, similar to isActor
418
+ return false ;
417
419
}
418
420
419
421
bool IsDistributedFuncRequest::evaluate (
@@ -1652,7 +1654,7 @@ namespace {
1652
1654
}
1653
1655
case ActorIsolationRestriction::CrossActorSelf:
1654
1656
case ActorIsolationRestriction::ActorSelf:
1655
- case ActorIsolationRestriction::DistributedActor : {
1657
+ case ActorIsolationRestriction::DistributedActorSelf : {
1656
1658
if (isPartialApply) {
1657
1659
// The partially applied InoutArg is a property of actor. This
1658
1660
// can really only happen when the property is a struct with a
@@ -2005,7 +2007,62 @@ namespace {
2005
2007
}
2006
2008
2007
2009
case ActorIsolation::Unspecified: {
2008
- // NOTE: we must always inspect for implicit effects (async or throws)
2010
+ // // NOTE: we must always inspect for implicit effects (async or throws)
2011
+ // auto result = tryMarkImplicitlyAsync(loc, valueRef, context);
2012
+ // bool implicitlyAsyncExpr = (result == AsyncMarkingResult::FoundAsync);
2013
+ // bool didEmitDiagnostic = false;
2014
+ //
2015
+ // if (result == AsyncMarkingResult::FoundAsync)
2016
+ // return false;
2017
+ //
2018
+ // // Diagnose the reference.
2019
+ // auto useKind = static_cast<unsigned>(
2020
+ // kindOfUsage(value, context).getValueOr(VarRefUseEnv::Read));
2021
+ // ctx.Diags.diagnose(
2022
+ // loc, diag::global_actor_from_nonactor_context,
2023
+ // value->getDescriptiveKind(), value->getName(), globalActor,
2024
+ // /*actorIndependent=*/false, useKind,
2025
+ // result == AsyncMarkingResult::SyncContext);
2026
+ //
2027
+ // if (AbstractFunctionDecl const* fn =
2028
+ // dyn_cast_or_null<AbstractFunctionDecl>(declContext->getAsDecl())) {
2029
+ // bool isAsyncContext = fn->isAsyncContext();
2030
+ //
2031
+ // if (implicitlyAsyncExpr && isAsyncContext)
2032
+ // return didEmitDiagnostic; // definitely an OK reference.
2033
+ //
2034
+ // // otherwise, there's something wrong.
2035
+ //
2036
+ // // if it's an implicitly-async call in a non-async context,
2037
+ // // then we know later type-checking will raise an error,
2038
+ // // so we just emit a note pointing out that callee of the call is
2039
+ // // implicitly async.
2040
+ // emitError(/*justNote=*/implicitlyAsyncExpr);
2041
+ //
2042
+ // // otherwise, if it's any kind of global-actor reference within
2043
+ // // this synchronous function, we'll additionally suggest becoming
2044
+ // // part of the global actor associated with the reference,
2045
+ // // since this function is not associated with an actor.
2046
+ // if (isa<FuncDecl>(fn) && !isAsyncContext) {
2047
+ // didEmitDiagnostic = true;
2048
+ // fn->diagnose(diag::note_add_globalactor_to_function,
2049
+ // globalActor->getWithoutParens().getString(),
2050
+ // fn->getDescriptiveKind(),
2051
+ // fn->getName(),
2052
+ // globalActor)
2053
+ // .fixItInsert(fn->getAttributeInsertionLoc(false),
2054
+ // diag::insert_globalactor_attr, globalActor);
2055
+ // }
2056
+ //
2057
+ // } else {
2058
+ // // just the generic error with note.
2059
+ // emitError();
2060
+ // }
2061
+ //
2062
+ // return false;
2063
+ // } // end Unspecified case
2064
+ // } // end switch
2065
+ // llvm_unreachable("unhandled actor isolation kind!");
2009
2066
auto result = tryMarkImplicitlyAsync (loc, valueRef, context);
2010
2067
if (result == AsyncMarkingResult::FoundAsync)
2011
2068
return false ;
@@ -2014,47 +2071,28 @@ namespace {
2014
2071
auto useKind = static_cast <unsigned >(
2015
2072
kindOfUsage (value, context).getValueOr (VarRefUseEnv::Read));
2016
2073
ctx.Diags .diagnose (
2017
- loc, diag::global_actor_from_nonactor_context,
2018
- value->getDescriptiveKind (), value->getName (), globalActor,
2019
- /* actorIndependent=*/ false , useKind,
2020
- result == AsyncMarkingResult::SyncContext);
2021
-
2022
- if (AbstractFunctionDecl const * fn =
2023
- dyn_cast_or_null<AbstractFunctionDecl>(declContext->getAsDecl ())) {
2024
- bool isAsyncContext = fn->isAsyncContext ();
2025
-
2026
- if (implicitlyAsyncExpr && isAsyncContext)
2027
- return didEmitDiagnostic; // definitely an OK reference.
2028
-
2029
- // otherwise, there's something wrong.
2030
-
2031
- // if it's an implicitly-async call in a non-async context,
2032
- // then we know later type-checking will raise an error,
2033
- // so we just emit a note pointing out that callee of the call is
2034
- // implicitly async.
2035
- emitError (/* justNote=*/ implicitlyAsyncExpr);
2036
-
2037
- // otherwise, if it's any kind of global-actor reference within
2038
- // this synchronous function, we'll additionally suggest becoming
2039
- // part of the global actor associated with the reference,
2040
- // since this function is not associated with an actor.
2041
- if (isa<FuncDecl>(fn) && !isAsyncContext) {
2042
- didEmitDiagnostic = true ;
2074
+ loc, diag::global_actor_from_nonactor_context,
2075
+ value->getDescriptiveKind (), value->getName (), globalActor,
2076
+ /* actorIndependent=*/ false , useKind,
2077
+ result == AsyncMarkingResult::SyncContext);
2078
+
2079
+ // If we are in a synchronous function on the global actor,
2080
+ // suggest annotating with the global actor itself.
2081
+ if (auto fn = dyn_cast<FuncDecl>(declContext)) {
2082
+ if (!isa<AccessorDecl>(fn) && !fn->isAsyncContext ()) {
2043
2083
fn->diagnose (diag::note_add_globalactor_to_function,
2044
- globalActor->getWithoutParens ().getString (),
2045
- fn->getDescriptiveKind (),
2046
- fn->getName (),
2047
- globalActor)
2048
- .fixItInsert (fn->getAttributeInsertionLoc (false ),
2049
- diag::insert_globalactor_attr, globalActor);
2084
+ globalActor->getWithoutParens ().getString (),
2085
+ fn->getDescriptiveKind (),
2086
+ fn->getName (),
2087
+ globalActor)
2088
+ .fixItInsert (fn->getAttributeInsertionLoc (false ),
2089
+ diag::insert_globalactor_attr, globalActor);
2050
2090
}
2051
-
2052
- } else {
2053
- // just the generic error with note.
2054
- emitError ();
2055
2091
}
2056
2092
2057
- return didEmitDiagnostic;
2093
+ noteIsolatedActorMember (value, context, isDistributedActor);
2094
+
2095
+ return true ;
2058
2096
} // end Unspecified case
2059
2097
} // end switch
2060
2098
llvm_unreachable (" unhandled actor isolation kind!" );
@@ -2192,10 +2230,13 @@ namespace {
2192
2230
}
2193
2231
LLVM_FALLTHROUGH; // otherwise, it's invalid so diagnose it.
2194
2232
2195
- case ActorIsolationRestriction::ActorSelf: {
2233
+ case ActorIsolationRestriction::ActorSelf:
2234
+ case ActorIsolationRestriction::DistributedActorSelf: {
2196
2235
auto decl = concDecl.getDecl ();
2197
2236
ctx.Diags .diagnose (component.getLoc (),
2198
2237
diag::actor_isolated_keypath_component,
2238
+ /* isDistributed=*/ isolation.getKind () ==
2239
+ ActorIsolationRestriction::DistributedActorSelf,
2199
2240
decl->getDescriptiveKind (), decl->getName ());
2200
2241
diagnosed = true ;
2201
2242
break ;
@@ -2239,7 +2280,7 @@ namespace {
2239
2280
2240
2281
case ActorIsolationRestriction::CrossActorSelf:
2241
2282
case ActorIsolationRestriction::ActorSelf:
2242
- case ActorIsolationRestriction::DistributedActor: // TODO: is it DistributedActorSelf?
2283
+ case ActorIsolationRestriction::DistributedActorSelf:
2243
2284
llvm_unreachable (" non-member reference into an actor" );
2244
2285
2245
2286
case ActorIsolationRestriction::GlobalActorUnsafe:
@@ -2330,7 +2371,7 @@ namespace {
2330
2371
ConcurrentReferenceKind::CrossActor);
2331
2372
}
2332
2373
2333
- case ActorIsolationRestriction::DistributedActor : {
2374
+ case ActorIsolationRestriction::DistributedActorSelf : {
2334
2375
// / mark for later diagnostics that we have we're in a distributed actor.
2335
2376
isDistributedActor = true ;
2336
2377
@@ -2892,6 +2933,7 @@ static Optional<ActorIsolation> getIsolationFromWitnessedRequirements(
2892
2933
auto requirementIsolation = getActorIsolation (requirement);
2893
2934
switch (requirementIsolation) {
2894
2935
case ActorIsolation::ActorInstance:
2936
+ case ActorIsolation::DistributedActorInstance:
2895
2937
case ActorIsolation::Unspecified:
2896
2938
continue ;
2897
2939
@@ -2996,9 +3038,9 @@ ActorIsolation ActorIsolationRequest::evaluate(
2996
3038
if (auto nominal = value->getDeclContext ()->getSelfNominalTypeDecl ()) {
2997
3039
if (nominal->isActor () &&
2998
3040
(value->isInstanceMember () || isa<ConstructorDecl>(value))) {
2999
- defaultIsolation = classDecl ->isDistributedActor () ?
3000
- ActorIsolation::forDistributedActorInstance (classDecl ) :
3001
- ActorIsolation::forActorInstance (classDecl );
3041
+ defaultIsolation = nominal ->isDistributedActor () ?
3042
+ ActorIsolation::forDistributedActorInstance (nominal ) :
3043
+ ActorIsolation::forActorInstance (nominal );
3002
3044
} else if (isa<ConstructorDecl>(value)) {
3003
3045
defaultIsolation = ActorIsolation::forActorInstance (nominal);
3004
3046
}
@@ -3013,10 +3055,16 @@ ActorIsolation ActorIsolationRequest::evaluate(
3013
3055
switch (inferred) {
3014
3056
// FIXME: if the context is 'unsafe', is it fine to infer the 'safe' one?
3015
3057
case ActorIsolation::IndependentUnsafe:
3016
- case ActorIsolation::Independent:
3017
- value->getAttrs ().add (new (ctx) ActorIndependentAttr (
3018
- ActorIndependentKind::Safe, /* IsImplicit=*/ true ));
3058
+ case ActorIsolation::Independent: {
3059
+ auto var = dyn_cast<VarDecl>(value);
3060
+ if ((var && !var->isLet ()) || !var) {
3061
+ // It is illegal to add @actorIndependent to let properties,
3062
+ // and if we did this would fail in type checking attributes.
3063
+ value->getAttrs ().add (new (ctx) ActorIndependentAttr (
3064
+ ActorIndependentKind::Safe, /* IsImplicit=*/ true ));
3065
+ }
3019
3066
break ;
3067
+ }
3020
3068
3021
3069
case ActorIsolation::GlobalActorUnsafe:
3022
3070
if (!propagateUnsafe && !value->hasClangNode ()) {
0 commit comments