@@ -578,8 +578,10 @@ findMemberReference(Expr *expr) {
578578 return None;
579579}
580580
581- void swift::checkActorIsolation (const Expr *expr, const DeclContext *dc) {
582- class ActorIsolationWalker : public ASTWalker {
581+ namespace {
582+ // / Check for adherence to the actor isolation rules, emitting errors
583+ // / when actor-isolated declarations are used in an unsafe manner.
584+ class ActorIsolationChecker : public ASTWalker {
583585 ASTContext &ctx;
584586 SmallVector<const DeclContext *, 4 > contextStack;
585587
@@ -588,20 +590,25 @@ void swift::checkActorIsolation(const Expr *expr, const DeclContext *dc) {
588590 }
589591
590592 public:
591- ActorIsolationWalker (const DeclContext *dc) : ctx(dc->getASTContext ()) {
593+ ActorIsolationChecker (const DeclContext *dc) : ctx(dc->getASTContext ()) {
592594 contextStack.push_back (dc);
593595 }
594596
595- bool shouldWalkIntoSeparatelyCheckedClosure (ClosureExpr *expr) override {
596- return false ;
597- }
598-
599597 bool shouldWalkCaptureInitializerExpressions () override { return true ; }
600598
601599 bool shouldWalkIntoTapExpression () override { return false ; }
602600
601+ bool walkToDeclPre (Decl *D) override {
602+ // Don't walk into functions; they'll be handled separately.
603+ if (isa<AbstractFunctionDecl>(D))
604+ return false ;
605+
606+ return true ;
607+ }
608+
603609 std::pair<bool , Expr *> walkToExprPre (Expr *expr) override {
604610 if (auto *closure = dyn_cast<AbstractClosureExpr>(expr)) {
611+ closure->setActorIsolation (determineClosureIsolation (closure));
605612 contextStack.push_back (closure);
606613 return { true , expr };
607614 }
@@ -709,11 +716,8 @@ void swift::checkActorIsolation(const Expr *expr, const DeclContext *dc) {
709716 while (useContext != defContext) {
710717 // If we find an escaping closure, it can be run concurrently.
711718 if (auto closure = dyn_cast<AbstractClosureExpr>(useContext)) {
712- if (auto type = closure->getType ()) {
713- if (auto fnType = type->getAs <AnyFunctionType>())
714- if (!fnType->isNoEscape ())
715- return true ;
716- }
719+ if (isEscapingClosure (closure))
720+ return true ;
717721 }
718722
719723 // If we find a local function, it can escape and be run concurrently.
@@ -1010,10 +1014,144 @@ void swift::checkActorIsolation(const Expr *expr, const DeclContext *dc) {
10101014 }
10111015 llvm_unreachable (" unhandled actor isolation kind!" );
10121016 }
1017+
1018+ // / Determine whether this closure is escaping.
1019+ static bool isEscapingClosure (const AbstractClosureExpr *closure) {
1020+ if (auto type = closure->getType ()) {
1021+ if (auto fnType = type->getAs <AnyFunctionType>())
1022+ return !fnType->isNoEscape ();
1023+ }
1024+
1025+ return true ;
1026+ }
1027+
1028+ // / Determine the isolation of a particular closure.
1029+ // /
1030+ // / This function assumes that enclosing closures have already had their
1031+ // / isolation checked.
1032+ ClosureActorIsolation determineClosureIsolation (
1033+ AbstractClosureExpr *closure) {
1034+ // An escaping closure is always actor-independent.
1035+ if (isEscapingClosure (closure))
1036+ return ClosureActorIsolation::forIndependent ();
1037+
1038+ // A non-escaping closure gets its isolation from its context.
1039+ Optional<ActorIsolation> parentIsolation;
1040+ auto parentDC = closure->getParent ();
1041+ switch (parentDC->getContextKind ()) {
1042+ case DeclContextKind::AbstractClosureExpr: {
1043+ auto parentClosureIsolation = cast<AbstractClosureExpr>(parentDC)
1044+ ->getActorIsolation ();
1045+ switch (parentClosureIsolation) {
1046+ case ClosureActorIsolation::Independent:
1047+ parentIsolation = ActorIsolation::forIndependent (
1048+ ActorIndependentKind::Safe);
1049+ break ;
1050+
1051+ case ClosureActorIsolation::ActorInstance: {
1052+ auto selfDecl = parentClosureIsolation.getActorInstance ();
1053+ auto actorClass = selfDecl->getType ()->getRValueType ()
1054+ ->getClassOrBoundGenericClass ();
1055+ assert (actorClass && " Bad closure actor isolation?" );
1056+ parentIsolation = ActorIsolation::forActorInstance (actorClass);
1057+ break ;
1058+ }
1059+
1060+ case ClosureActorIsolation::GlobalActor:
1061+ parentIsolation = ActorIsolation::forGlobalActor (
1062+ parentClosureIsolation.getGlobalActor ());
1063+ break ;
1064+ }
1065+ break ;
1066+ }
1067+
1068+ case DeclContextKind::AbstractFunctionDecl:
1069+ case DeclContextKind::SubscriptDecl:
1070+ parentIsolation = getActorIsolation (
1071+ cast<ValueDecl>(parentDC->getAsDecl ()));
1072+ break ;
1073+
1074+ case DeclContextKind::EnumElementDecl:
1075+ case DeclContextKind::ExtensionDecl:
1076+ case DeclContextKind::FileUnit:
1077+ case DeclContextKind::GenericTypeDecl:
1078+ case DeclContextKind::Initializer:
1079+ case DeclContextKind::Module:
1080+ case DeclContextKind::SerializedLocal:
1081+ case DeclContextKind::TopLevelCodeDecl:
1082+ return ClosureActorIsolation::forIndependent ();
1083+ }
1084+
1085+ // We must have parent isolation determined to get here.
1086+ assert (parentIsolation && " Missing parent isolation?" );
1087+ switch (*parentIsolation) {
1088+ case ActorIsolation::Independent:
1089+ case ActorIsolation::IndependentUnsafe:
1090+ case ActorIsolation::Unspecified:
1091+ return ClosureActorIsolation::forIndependent ();
1092+
1093+ case ActorIsolation::GlobalActor: {
1094+ Type globalActorType = closure->mapTypeIntoContext (
1095+ parentIsolation->getGlobalActor ()->mapTypeOutOfContext ());
1096+ return ClosureActorIsolation::forGlobalActor (globalActorType);
1097+ }
1098+
1099+ case ActorIsolation::ActorInstance: {
1100+ SmallVector<CapturedValue, 2 > localCaptures;
1101+ closure->getCaptureInfo ().getLocalCaptures (localCaptures);
1102+ for (const auto &localCapture : localCaptures) {
1103+ if (localCapture.isDynamicSelfMetadata ())
1104+ continue ;
1105+
1106+ auto var = dyn_cast_or_null<VarDecl>(localCapture.getDecl ());
1107+ if (!var)
1108+ continue ;
1109+
1110+ // If we have captured the 'self' parameter, the closure is isolated
1111+ // to that actor instance.
1112+ if (var->isSelfParameter ()) {
1113+ return ClosureActorIsolation::forActorInstance (var);
1114+ }
1115+ }
1116+
1117+ // When 'self' is not captured, this closure is actor-independent.
1118+ return ClosureActorIsolation::forIndependent ();
1119+ }
1120+ }
1121+ }
10131122 };
1123+ }
1124+
1125+ void swift::checkTopLevelActorIsolation (TopLevelCodeDecl *decl) {
1126+ ActorIsolationChecker checker (decl);
1127+ decl->getBody ()->walk (checker);
1128+ }
1129+
1130+ void swift::checkFunctionActorIsolation (AbstractFunctionDecl *decl) {
1131+ ActorIsolationChecker checker (decl);
1132+ if (auto body = decl->getBody ()) {
1133+ body->walk (checker);
1134+ }
1135+ if (auto ctor = dyn_cast<ConstructorDecl>(decl))
1136+ if (auto superInit = ctor->getSuperInitCall ())
1137+ superInit->walk (checker);
1138+ }
1139+
1140+ void swift::checkInitializerActorIsolation (Initializer *init, Expr *expr) {
1141+ ActorIsolationChecker checker (init);
1142+ expr->walk (checker);
1143+ }
1144+
1145+ void swift::checkEnumElementActorIsolation (
1146+ EnumElementDecl *element, Expr *expr) {
1147+ ActorIsolationChecker checker (element);
1148+ expr->walk (checker);
1149+ }
10141150
1015- ActorIsolationWalker walker (dc);
1016- const_cast <Expr *>(expr)->walk (walker);
1151+ void swift::checkPropertyWrapperActorIsolation (
1152+ PatternBindingDecl *binding, Expr *expr) {
1153+ ActorIsolationChecker checker (binding->getDeclContext ());
1154+ expr->walk (checker);
10171155}
10181156
10191157// / Determine actor isolation solely from attributes.
0 commit comments