Skip to content

Commit 75152e7

Browse files
committed
[region-isolation] Teach region isolation how to handle cases where due to compiler bugs, we have a function isolated to self without an isolated parameter.
Closures generally only inherit actor instance isolation if they directly capture state from the actor instance. In this case, for some reason that is not true, so we hit an assert that assumes that we will only see a global actor isolated isolation. Region Isolation should be able to handle code even if the closure isolation invariant is violated by the frontend. So to do this, I am introducing a new singleton actor instance to represent the isolation of a defer or closure created in an actor instance isolated method. The reason why I am using a singleton is that closures and defer are not methods so we do not actually know which parameter is 'self' since it isn't in the abi. But we still need some value to represent the captured values as belonging to. To square this circle, I just did what we have done in a similar situation where we did not have a value: (ActorAccessorInit). In that case, we just use a sentinel to represent the instance (NOTE: This is represented just via a kind so ActorInstances that are operator== equal will not &value equal since we are just using a kind).
1 parent 0b42f35 commit 75152e7

File tree

4 files changed

+58
-6
lines changed

4 files changed

+58
-6
lines changed

include/swift/SILOptimizer/Utils/SILIsolationInfo.h

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,18 @@ class ActorInstance {
4646
/// access to the self value and instead have access indirectly to the
4747
/// storage associated with the accessor.
4848
ActorAccessorInit = 0x1,
49+
50+
/// An actor instance that is represented by "self" being captured in a
51+
/// closure of some sort. In such a case, we do not know which of the
52+
/// parameters are the true "self" (since the closure is a thin
53+
/// function)... so we just use an artificial ActorInstance to represent
54+
/// self in this case.
55+
CapturedActorSelf = 0x2,
4956
};
5057

51-
/// Set to (SILValue(), ActorAccessorInit) if we have an ActorAccessorInit. Is
52-
/// null if we have (SILValue(), Kind::Value).
53-
llvm::PointerIntPair<SILValue, 1> value;
58+
/// Set to (SILValue(), $KIND) if we have an ActorAccessorInit|CapturedSelf.
59+
/// Is null if we have (SILValue(), Kind::Value).
60+
llvm::PointerIntPair<SILValue, 2> value;
5461

5562
ActorInstance(SILValue value, Kind kind)
5663
: value(value, std::underlying_type<Kind>::type(kind)) {}
@@ -68,10 +75,18 @@ class ActorInstance {
6875
return ActorInstance(value, Kind::Value);
6976
}
7077

78+
/// See Kind::ActorAccessorInit for explanation on what a ActorAccessorInit
79+
/// is.
7180
static ActorInstance getForActorAccessorInit() {
7281
return ActorInstance(SILValue(), Kind::ActorAccessorInit);
7382
}
7483

84+
/// See Kind::CapturedActorSelf for explanation on what a CapturedActorSelf
85+
/// is.
86+
static ActorInstance getForCapturedSelf() {
87+
return ActorInstance(SILValue(), Kind::CapturedActorSelf);
88+
}
89+
7590
explicit operator bool() const { return bool(value.getOpaqueValue()); }
7691

7792
Kind getKind() const { return Kind(value.getInt()); }
@@ -91,6 +106,10 @@ class ActorInstance {
91106

92107
bool isAccessorInit() const { return getKind() == Kind::ActorAccessorInit; }
93108

109+
bool isCapturedActorSelf() const {
110+
return getKind() == Kind::CapturedActorSelf;
111+
}
112+
94113
bool operator==(const ActorInstance &other) const {
95114
// If both are null, return true.
96115
if (!bool(*this) && !bool(other))
@@ -105,6 +124,7 @@ class ActorInstance {
105124
case Kind::Value:
106125
return getValue() == other.getValue();
107126
case Kind::ActorAccessorInit:
127+
case Kind::CapturedActorSelf:
108128
return true;
109129
}
110130
}

lib/SILOptimizer/Utils/SILIsolationInfo.cpp

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -879,8 +879,14 @@ SILIsolationInfo SILIsolationInfo::get(SILArgument *arg) {
879879
if (auto functionIsolation = fArg->getFunction()->getActorIsolation()) {
880880
if (functionIsolation.isActorIsolated()) {
881881
assert(functionIsolation.isGlobalActor());
882-
return SILIsolationInfo::getGlobalActorIsolated(
883-
fArg, functionIsolation.getGlobalActor());
882+
if (functionIsolation.isGlobalActor()) {
883+
return SILIsolationInfo::getGlobalActorIsolated(
884+
fArg, functionIsolation.getGlobalActor());
885+
}
886+
887+
return SILIsolationInfo::getActorInstanceIsolated(
888+
fArg, ActorInstance::getForActorAccessorInit(),
889+
functionIsolation.getActor());
884890
}
885891
}
886892

@@ -944,6 +950,12 @@ void SILIsolationInfo::print(llvm::raw_ostream &os) const {
944950
os << '\n';
945951
os << "instance: actor accessor init\n";
946952
return;
953+
case ActorInstance::Kind::CapturedActorSelf:
954+
os << "'self'-isolated";
955+
printOptions(os);
956+
os << '\n';
957+
os << "instance: captured actor instance self\n";
958+
return;
947959
}
948960
}
949961

@@ -1062,6 +1074,9 @@ void SILIsolationInfo::printForDiagnostics(llvm::raw_ostream &os) const {
10621074
case ActorInstance::Kind::ActorAccessorInit:
10631075
os << "'self'-isolated";
10641076
return;
1077+
case ActorInstance::Kind::CapturedActorSelf:
1078+
os << "'self'-isolated";
1079+
return;
10651080
}
10661081
}
10671082

@@ -1102,7 +1117,11 @@ void SILIsolationInfo::printForOneLineLogging(llvm::raw_ostream &os) const {
11021117
break;
11031118
}
11041119
case ActorInstance::Kind::ActorAccessorInit:
1105-
os << "'self'-isolated";
1120+
os << "'self'-isolated (actor-accessor-init)";
1121+
printOptions(os);
1122+
return;
1123+
case ActorInstance::Kind::CapturedActorSelf:
1124+
os << "'self'-isolated (captured-actor-self)";
11061125
printOptions(os);
11071126
return;
11081127
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11

2+
@import Foundation;
3+
24
@interface MyNotificationCenter
35
- (id)init;
46
- (void)post;
57
@end
8+
9+
@protocol MySession <NSObject>
10+
- (void)endSession;
11+
@end

test/Concurrency/transfernonsendable_crashers_objc.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,10 @@ public func handleFile(at location: URL) throws {
1818

1919
private func moveTheme(from location: URL) throws -> URL { fatalError() }
2020
private func unzipFile(at location: URL) throws -> URL { fatalError() }
21+
22+
actor MyActor {
23+
func test() {
24+
var session: MySession?
25+
defer { session?.end() }
26+
}
27+
}

0 commit comments

Comments
 (0)