@@ -578,8 +578,10 @@ findMemberReference(Expr *expr) {
578
578
return None;
579
579
}
580
580
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 {
583
585
ASTContext &ctx;
584
586
SmallVector<const DeclContext *, 4 > contextStack;
585
587
@@ -588,20 +590,25 @@ void swift::checkActorIsolation(const Expr *expr, const DeclContext *dc) {
588
590
}
589
591
590
592
public:
591
- ActorIsolationWalker (const DeclContext *dc) : ctx(dc->getASTContext ()) {
593
+ ActorIsolationChecker (const DeclContext *dc) : ctx(dc->getASTContext ()) {
592
594
contextStack.push_back (dc);
593
595
}
594
596
595
- bool shouldWalkIntoSeparatelyCheckedClosure (ClosureExpr *expr) override {
596
- return false ;
597
- }
598
-
599
597
bool shouldWalkCaptureInitializerExpressions () override { return true ; }
600
598
601
599
bool shouldWalkIntoTapExpression () override { return false ; }
602
600
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
+
603
609
std::pair<bool , Expr *> walkToExprPre (Expr *expr) override {
604
610
if (auto *closure = dyn_cast<AbstractClosureExpr>(expr)) {
611
+ closure->setActorIsolation (determineClosureIsolation (closure));
605
612
contextStack.push_back (closure);
606
613
return { true , expr };
607
614
}
@@ -709,11 +716,8 @@ void swift::checkActorIsolation(const Expr *expr, const DeclContext *dc) {
709
716
while (useContext != defContext) {
710
717
// If we find an escaping closure, it can be run concurrently.
711
718
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 ;
717
721
}
718
722
719
723
// 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) {
1010
1014
}
1011
1015
llvm_unreachable (" unhandled actor isolation kind!" );
1012
1016
}
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
+ }
1013
1122
};
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
+ }
1014
1150
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);
1017
1155
}
1018
1156
1019
1157
// / Determine actor isolation solely from attributes.
0 commit comments