Skip to content

Commit 0cb6463

Browse files
committed
[concurrency] Add Concurrent/ConcurrentUnsafe and use it instead of ActorIsolation::Nonisolated.
This is just the first part of a larger transition.
1 parent 85faa52 commit 0cb6463

30 files changed

+387
-225
lines changed

include/swift/AST/ActorIsolation.h

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,19 @@ class ActorIsolation {
5757
/// the actor is isolated to the instance of that actor.
5858
ActorInstance,
5959
/// The declaration is explicitly specified to be not isolated to any actor,
60-
/// meaning that it can be used from any actor but is also unable to
61-
/// refer to the isolated state of any given actor.
60+
/// meaning it cannot itself access actor isolated state but /does/ allow
61+
/// for indirect access to actor isolated state if the declaration can
62+
/// guarantee that all code generated to work with the declaration will run
63+
/// on said actor.
64+
///
65+
/// E.x.: a nonisolated function can accept actor-isolated values as
66+
/// arguments since the caller knows that it will not escape the values to
67+
/// another isolation domain and that the function will remain on the
68+
/// caller's actor.
69+
///
70+
/// NOTE: This used to have the meaning of Concurrent which is a stricter
71+
/// definition of nonisolated that prevents the code generated to work with
72+
/// the declaration to never touch actor isolated state.
6273
Nonisolated,
6374
/// The declaration is explicitly specified to be not isolated and with the
6475
/// "unsafe" annotation, which means that we do not enforce isolation.
@@ -74,6 +85,20 @@ class ActorIsolation {
7485
/// DISCUSSION: This is used for nonisolated asynchronous functions that we
7586
/// want to inherit from their context the context's actor isolation.
7687
CallerIsolationInheriting,
88+
/// The declaration is explicitly specified to be not isolated to any actor,
89+
/// meaning that it can be used from any actor but is also unable to
90+
/// refer to the isolated state of any given actor.
91+
///
92+
/// NOTE: This used to be nonisolated, but we changed nonisolated to have a
93+
/// weaker definition of nonisolated that allows for actor isolated state to
94+
/// be manipulated by code generated to work with the actor as long as all
95+
/// such code generation is guaranteed to always run on whatever actor
96+
/// isolation it is invoked in consistently and not escape the value to any
97+
/// other isolation domain.
98+
Concurrent,
99+
/// The declaration is explicitly specified to be concurrent and with the
100+
/// "unsafe" annotation, which means that we do not enforce isolation.
101+
ConcurrentUnsafe,
77102
};
78103

79104
private:
@@ -82,13 +107,13 @@ class ActorIsolation {
82107
Type globalActor;
83108
void *pointer;
84109
};
85-
unsigned kind : 3;
110+
unsigned kind : 4;
86111
unsigned isolatedByPreconcurrency : 1;
87112

88113
/// Set to true if this was parsed from SIL.
89114
unsigned silParsed : 1;
90115

91-
unsigned parameterIndex : 27;
116+
unsigned parameterIndex : 26;
92117

93118
ActorIsolation(Kind kind, NominalTypeDecl *actor, unsigned parameterIndex);
94119

@@ -112,6 +137,10 @@ class ActorIsolation {
112137
return ActorIsolation(unsafe ? NonisolatedUnsafe : Nonisolated);
113138
}
114139

140+
static ActorIsolation forConcurrent(bool unsafe) {
141+
return ActorIsolation(unsafe ? ConcurrentUnsafe : Concurrent);
142+
}
143+
115144
static ActorIsolation forCallerIsolationInheriting() {
116145
// NOTE: We do not use parameter indices since the parameter is implicit
117146
// from the perspective of the AST.
@@ -168,6 +197,10 @@ class ActorIsolation {
168197
.Case("caller_isolation_inheriting",
169198
std::optional<ActorIsolation>(
170199
ActorIsolation::CallerIsolationInheriting))
200+
.Case("concurrent",
201+
std::optional<ActorIsolation>(ActorIsolation::Concurrent))
202+
.Case("concurrent_unsafe", std::optional<ActorIsolation>(
203+
ActorIsolation::ConcurrentUnsafe))
171204
.Default(std::nullopt);
172205
if (kind == std::nullopt)
173206
return std::nullopt;
@@ -180,12 +213,22 @@ class ActorIsolation {
180213

181214
bool isUnspecified() const { return kind == Unspecified; }
182215

216+
bool isConcurrent() const {
217+
return (kind == Concurrent) || (kind == ConcurrentUnsafe);
218+
}
219+
220+
bool isConcurrentUnsafe() const { return kind == ConcurrentUnsafe; }
221+
183222
bool isNonisolated() const {
184223
return (kind == Nonisolated) || (kind == NonisolatedUnsafe);
185224
}
186225

187226
bool isNonisolatedUnsafe() const { return kind == NonisolatedUnsafe; }
188227

228+
bool isUnsafe() const {
229+
return kind == NonisolatedUnsafe || kind == ConcurrentUnsafe;
230+
}
231+
189232
/// Retrieve the parameter to which actor-instance isolation applies.
190233
///
191234
/// Parameter 0 is `self`.
@@ -213,6 +256,8 @@ class ActorIsolation {
213256
case Nonisolated:
214257
case NonisolatedUnsafe:
215258
case CallerIsolationInheriting:
259+
case Concurrent:
260+
case ConcurrentUnsafe:
216261
return false;
217262
}
218263
}

lib/AST/ASTDumper.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3844,12 +3844,17 @@ class PrintExpr : public ExprVisitor<PrintExpr, void, Label>,
38443844
switch (auto isolation = E->getActorIsolation()) {
38453845
case ActorIsolation::Unspecified:
38463846
case ActorIsolation::NonisolatedUnsafe:
3847+
case ActorIsolation::ConcurrentUnsafe:
38473848
break;
38483849

38493850
case ActorIsolation::Nonisolated:
38503851
printFlag(true, "nonisolated", CapturesColor);
38513852
break;
38523853

3854+
case ActorIsolation::Concurrent:
3855+
printFlag(true, "concurrent", CapturesColor);
3856+
break;
3857+
38533858
case ActorIsolation::Erased:
38543859
printFlag(true, "dynamically_isolated", CapturesColor);
38553860
break;

lib/AST/ActorIsolation.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@ ActorIsolation::ActorIsolation(Kind kind, Expr *actor, unsigned parameterIndex)
3939

4040
ActorIsolation::ActorIsolation(Kind kind, Type globalActor)
4141
: globalActor(globalActor), kind(kind), isolatedByPreconcurrency(false),
42-
silParsed(false), parameterIndex(0) {}
42+
silParsed(false), parameterIndex(0) {
43+
assert((silParsed || globalActor) &&
44+
"If we are not sil parsed, global actor must be a real type");
45+
}
4346

4447
ActorIsolation
4548
ActorIsolation::forActorInstanceParameter(Expr *actor,
@@ -49,7 +52,7 @@ ActorIsolation::forActorInstanceParameter(Expr *actor,
4952
// An isolated value of `nil` is statically nonisolated.
5053
// FIXME: Also allow 'Optional.none'
5154
if (isa<NilLiteralExpr>(actor))
52-
return ActorIsolation::forNonisolated(/*unsafe*/ false);
55+
return ActorIsolation::forConcurrent(/*unsafe*/ false);
5356

5457
// An isolated value of `<global actor type>.shared` is statically
5558
// global actor isolated.
@@ -164,6 +167,8 @@ bool ActorIsolation::isEqual(const ActorIsolation &lhs,
164167
switch (lhs.getKind()) {
165168
case Nonisolated:
166169
case NonisolatedUnsafe:
170+
case Concurrent:
171+
case ConcurrentUnsafe:
167172
case Unspecified:
168173
return true;
169174

lib/AST/Decl.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2757,6 +2757,7 @@ static bool deferMatchesEnclosingAccess(const FuncDecl *defer) {
27572757
switch (isolation) {
27582758
case ActorIsolation::Unspecified:
27592759
case ActorIsolation::NonisolatedUnsafe:
2760+
case ActorIsolation::ConcurrentUnsafe:
27602761
break;
27612762

27622763
case ActorIsolation::GlobalActor:
@@ -2768,6 +2769,7 @@ static bool deferMatchesEnclosingAccess(const FuncDecl *defer) {
27682769
case ActorIsolation::CallerIsolationInheriting:
27692770
case ActorIsolation::ActorInstance:
27702771
case ActorIsolation::Nonisolated:
2772+
case ActorIsolation::Concurrent:
27712773
case ActorIsolation::Erased: // really can't happen
27722774
return true;
27732775
}
@@ -11458,6 +11460,8 @@ bool VarDecl::isSelfParamCaptureIsolated() const {
1145811460
case ActorIsolation::Unspecified:
1145911461
case ActorIsolation::Nonisolated:
1146011462
case ActorIsolation::NonisolatedUnsafe:
11463+
case ActorIsolation::Concurrent:
11464+
case ActorIsolation::ConcurrentUnsafe:
1146111465
case ActorIsolation::GlobalActor:
1146211466
case ActorIsolation::Erased:
1146311467
case ActorIsolation::CallerIsolationInheriting:

lib/AST/TypeCheckRequests.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1860,6 +1860,8 @@ bool ActorIsolation::requiresSubstitution() const {
18601860
case ActorInstance:
18611861
case Nonisolated:
18621862
case NonisolatedUnsafe:
1863+
case Concurrent:
1864+
case ConcurrentUnsafe:
18631865
case Unspecified:
18641866
return false;
18651867

@@ -1875,6 +1877,8 @@ ActorIsolation ActorIsolation::subst(SubstitutionMap subs) const {
18751877
case CallerIsolationInheriting:
18761878
case Nonisolated:
18771879
case NonisolatedUnsafe:
1880+
case Concurrent:
1881+
case ConcurrentUnsafe:
18781882
case Unspecified:
18791883
return *this;
18801884

@@ -1912,11 +1916,13 @@ void ActorIsolation::printForDiagnostics(llvm::raw_ostream &os,
19121916
os << "@isolated(any)";
19131917
break;
19141918

1919+
case ActorIsolation::Concurrent:
1920+
case ActorIsolation::ConcurrentUnsafe:
19151921
case ActorIsolation::Nonisolated:
19161922
case ActorIsolation::NonisolatedUnsafe:
19171923
case ActorIsolation::Unspecified:
19181924
os << "nonisolated";
1919-
if (*this == ActorIsolation::NonisolatedUnsafe) {
1925+
if (isUnsafe()) {
19201926
os << "(unsafe)";
19211927
}
19221928
break;
@@ -1943,6 +1949,12 @@ void ActorIsolation::print(llvm::raw_ostream &os) const {
19431949
case NonisolatedUnsafe:
19441950
os << "nonisolated_unsafe";
19451951
return;
1952+
case Concurrent:
1953+
os << "concurrent";
1954+
return;
1955+
case ConcurrentUnsafe:
1956+
os << "concurrent_unsafe";
1957+
return;
19461958
case GlobalActor:
19471959
os << "global_actor. type: " << getGlobalActor();
19481960
return;
@@ -1970,6 +1982,12 @@ void ActorIsolation::printForSIL(llvm::raw_ostream &os) const {
19701982
case NonisolatedUnsafe:
19711983
os << "nonisolated_unsafe";
19721984
return;
1985+
case Concurrent:
1986+
os << "concurrent";
1987+
return;
1988+
case ConcurrentUnsafe:
1989+
os << "concurrent_unsafe";
1990+
return;
19731991
case GlobalActor:
19741992
os << "global_actor";
19751993
return;
@@ -2015,8 +2033,10 @@ void swift::simple_display(
20152033

20162034
case ActorIsolation::Nonisolated:
20172035
case ActorIsolation::NonisolatedUnsafe:
2036+
case ActorIsolation::Concurrent:
2037+
case ActorIsolation::ConcurrentUnsafe:
20182038
out << "nonisolated";
2019-
if (state == ActorIsolation::NonisolatedUnsafe) {
2039+
if (state.isUnsafe()) {
20202040
out << "(unsafe)";
20212041
}
20222042
break;

lib/IDE/CompletionLookup.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -827,8 +827,10 @@ void CompletionLookup::analyzeActorIsolation(
827827
break;
828828
case ActorIsolation::Unspecified:
829829
case ActorIsolation::Nonisolated:
830-
case ActorIsolation::CallerIsolationInheriting:
831830
case ActorIsolation::NonisolatedUnsafe:
831+
case ActorIsolation::Concurrent:
832+
case ActorIsolation::ConcurrentUnsafe:
833+
case ActorIsolation::CallerIsolationInheriting:
832834
return;
833835
}
834836
}

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2530,12 +2530,12 @@ static CanSILFunctionType getSILFunctionType(
25302530
std::optional<ActorIsolation> actorIsolation;
25312531
if (constant) {
25322532
if (constant->kind == SILDeclRef::Kind::Deallocator) {
2533-
actorIsolation = ActorIsolation::forNonisolated(false);
2533+
actorIsolation = ActorIsolation::forConcurrent(false);
25342534
} else if (auto *decl = constant->getAbstractFunctionDecl();
25352535
decl && decl->getExecutionBehavior().has_value()) {
25362536
switch (*decl->getExecutionBehavior()) {
25372537
case ExecutionKind::Concurrent:
2538-
actorIsolation = ActorIsolation::forNonisolated(false /*unsafe*/);
2538+
actorIsolation = ActorIsolation::forConcurrent(false /*unsafe*/);
25392539
break;
25402540
case ExecutionKind::Caller:
25412541
actorIsolation = ActorIsolation::forCallerIsolationInheriting();

lib/SILGen/SILGen.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,7 @@ static ActorIsolation getActorIsolationForFunction(SILFunction &fn) {
735735
if (constant.kind == SILDeclRef::Kind::Deallocator) {
736736
// Deallocating destructor is always nonisolated. Isolation of the deinit
737737
// applies only to isolated deallocator and destroyer.
738-
return ActorIsolation::forNonisolated(false);
738+
return ActorIsolation::forConcurrent(false);
739739
}
740740

741741
// If we have actor isolation for our constant, put the isolation onto the

lib/SILGen/SILGenApply.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3104,8 +3104,10 @@ static void emitDelayedArguments(SILGenFunction &SGF,
31043104

31053105
case ActorIsolation::Unspecified:
31063106
case ActorIsolation::Nonisolated:
3107-
case ActorIsolation::CallerIsolationInheriting:
31083107
case ActorIsolation::NonisolatedUnsafe:
3108+
case ActorIsolation::Concurrent:
3109+
case ActorIsolation::ConcurrentUnsafe:
3110+
case ActorIsolation::CallerIsolationInheriting:
31093111
llvm_unreachable("Not isolated");
31103112
}
31113113

@@ -5832,8 +5834,10 @@ RValue SILGenFunction::emitApply(
58325834

58335835
case ActorIsolation::Unspecified:
58345836
case ActorIsolation::Nonisolated:
5835-
case ActorIsolation::CallerIsolationInheriting:
58365837
case ActorIsolation::NonisolatedUnsafe:
5838+
case ActorIsolation::Concurrent:
5839+
case ActorIsolation::ConcurrentUnsafe:
5840+
case ActorIsolation::CallerIsolationInheriting:
58375841
llvm_unreachable("Not isolated");
58385842
break;
58395843
}

lib/SILGen/SILGenConcurrency.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ void SILGenFunction::emitExpectedExecutorProlog() {
106106
// the instance properties of the class.
107107
return false;
108108

109+
case ActorIsolation::Concurrent:
110+
case ActorIsolation::ConcurrentUnsafe:
109111
case ActorIsolation::Nonisolated:
110112
case ActorIsolation::NonisolatedUnsafe:
111113
case ActorIsolation::Unspecified:
@@ -165,6 +167,8 @@ void SILGenFunction::emitExpectedExecutorProlog() {
165167
case ActorIsolation::Unspecified:
166168
case ActorIsolation::Nonisolated:
167169
case ActorIsolation::NonisolatedUnsafe:
170+
case ActorIsolation::Concurrent:
171+
case ActorIsolation::ConcurrentUnsafe:
168172
break;
169173

170174
case ActorIsolation::Erased:
@@ -205,8 +209,10 @@ void SILGenFunction::emitExpectedExecutorProlog() {
205209
switch (actorIsolation.getKind()) {
206210
case ActorIsolation::Unspecified:
207211
case ActorIsolation::Nonisolated:
208-
case ActorIsolation::CallerIsolationInheriting:
209212
case ActorIsolation::NonisolatedUnsafe:
213+
case ActorIsolation::Concurrent:
214+
case ActorIsolation::ConcurrentUnsafe:
215+
case ActorIsolation::CallerIsolationInheriting:
210216
break;
211217

212218
case ActorIsolation::Erased:
@@ -633,8 +639,10 @@ SILGenFunction::emitClosureIsolation(SILLocation loc, SILDeclRef constant,
633639
switch (isolation) {
634640
case ActorIsolation::Unspecified:
635641
case ActorIsolation::Nonisolated:
636-
case ActorIsolation::CallerIsolationInheriting:
637642
case ActorIsolation::NonisolatedUnsafe:
643+
case ActorIsolation::Concurrent:
644+
case ActorIsolation::ConcurrentUnsafe:
645+
case ActorIsolation::CallerIsolationInheriting:
638646
return emitNonIsolatedIsolation(loc);
639647

640648
case ActorIsolation::Erased:
@@ -685,8 +693,10 @@ SILGenFunction::emitExecutor(SILLocation loc, ActorIsolation isolation,
685693
switch (isolation.getKind()) {
686694
case ActorIsolation::Unspecified:
687695
case ActorIsolation::Nonisolated:
688-
case ActorIsolation::CallerIsolationInheriting:
689696
case ActorIsolation::NonisolatedUnsafe:
697+
case ActorIsolation::Concurrent:
698+
case ActorIsolation::ConcurrentUnsafe:
699+
case ActorIsolation::CallerIsolationInheriting:
690700
return std::nullopt;
691701

692702
case ActorIsolation::Erased:
@@ -716,6 +726,8 @@ void SILGenFunction::emitHopToActorValue(SILLocation loc, ManagedValue actor) {
716726
});
717727
if (isolation != ActorIsolation::Nonisolated &&
718728
isolation != ActorIsolation::NonisolatedUnsafe &&
729+
isolation != ActorIsolation::Concurrent &&
730+
isolation != ActorIsolation::ConcurrentUnsafe &&
719731
isolation != ActorIsolation::Unspecified) {
720732
// TODO: Explicit hop with no hop-back should only be allowed in nonisolated
721733
// async functions. But it needs work for any closure passed to

lib/SILGen/SILGenConstructor.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,8 @@ static bool ctorHopsInjectedByDefiniteInit(ConstructorDecl *ctor,
603603
case ActorIsolation::Unspecified:
604604
case ActorIsolation::Nonisolated:
605605
case ActorIsolation::NonisolatedUnsafe:
606+
case ActorIsolation::Concurrent:
607+
case ActorIsolation::ConcurrentUnsafe:
606608
case ActorIsolation::GlobalActor:
607609
case ActorIsolation::CallerIsolationInheriting:
608610
return false;
@@ -1558,6 +1560,8 @@ void SILGenFunction::emitMemberInitializer(DeclContext *dc, VarDecl *selfDecl,
15581560
case ActorIsolation::Unspecified:
15591561
case ActorIsolation::Nonisolated:
15601562
case ActorIsolation::NonisolatedUnsafe:
1563+
case ActorIsolation::Concurrent:
1564+
case ActorIsolation::ConcurrentUnsafe:
15611565
case ActorIsolation::CallerIsolationInheriting:
15621566
break;
15631567

0 commit comments

Comments
 (0)