Skip to content

Commit 35a5a25

Browse files
committed
[region-isolation] Fix isolation inference for init accessors.
rdar://127844737
1 parent 50c2d67 commit 35a5a25

File tree

5 files changed

+210
-44
lines changed

5 files changed

+210
-44
lines changed

include/swift/SILOptimizer/Utils/PartitionUtils.h

Lines changed: 86 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,65 @@ struct DenseMapInfo<swift::PartitionPrimitives::Region> {
9595

9696
namespace swift {
9797

98+
class ActorInstance {
99+
public:
100+
enum class Kind : uint8_t {
101+
Value,
102+
ActorAccessorInit = 0x1,
103+
};
104+
105+
llvm::PointerIntPair<SILValue, 1> value;
106+
107+
ActorInstance(SILValue value, Kind kind)
108+
: value(value, std::underlying_type<Kind>::type(kind)) {}
109+
110+
public:
111+
ActorInstance() : ActorInstance(SILValue(), Kind::Value) {}
112+
113+
static ActorInstance getForValue(SILValue value) {
114+
return ActorInstance(value, Kind::Value);
115+
}
116+
117+
static ActorInstance getForActorAccessorInit() {
118+
return ActorInstance(SILValue(), Kind::ActorAccessorInit);
119+
}
120+
121+
explicit operator bool() const { return bool(value.getOpaqueValue()); }
122+
123+
Kind getKind() const { return Kind(value.getInt()); }
124+
125+
SILValue getValue() const {
126+
assert(getKind() == Kind::Value);
127+
return value.getPointer();
128+
}
129+
130+
bool isValue() const { return getKind() == Kind::Value; }
131+
132+
bool isAccessorInit() const { return getKind() == Kind::ActorAccessorInit; }
133+
134+
bool operator==(const ActorInstance &other) const {
135+
// If both are null, return true.
136+
if (!bool(*this) && !bool(other))
137+
return true;
138+
139+
// Otherwise, check if the kinds match.
140+
if (getKind() != other.getKind())
141+
return false;
142+
143+
// Now that we know that the kinds match, perform the kind specific check.
144+
switch (getKind()) {
145+
case Kind::Value:
146+
return getValue() == other.getValue();
147+
case Kind::ActorAccessorInit:
148+
return true;
149+
}
150+
}
151+
152+
bool operator!=(const ActorInstance &other) const {
153+
return !(*this == other);
154+
}
155+
};
156+
98157
class SILIsolationInfo {
99158
public:
100159
/// The lattice is:
@@ -122,18 +181,29 @@ class SILIsolationInfo {
122181

123182
/// If set this is the SILValue that represents the actor instance that we
124183
/// derived isolatedValue from.
125-
SILValue actorInstance;
184+
///
185+
/// If set to (SILValue(), 1), then we are in an
186+
ActorInstance actorInstance;
126187

127188
SILIsolationInfo(SILValue isolatedValue, SILValue actorInstance,
128189
ActorIsolation actorIsolation)
129190
: kind(Actor), actorIsolation(actorIsolation),
130-
isolatedValue(isolatedValue), actorInstance(actorInstance) {
191+
isolatedValue(isolatedValue),
192+
actorInstance(ActorInstance::getForValue(actorInstance)) {
131193
assert((!actorInstance ||
132194
(actorIsolation.getKind() == ActorIsolation::ActorInstance &&
133195
actorInstance->getType().isAnyActor())) &&
134196
"actorInstance must be an actor if it is non-empty");
135197
}
136198

199+
SILIsolationInfo(SILValue isolatedValue, ActorInstance actorInstance,
200+
ActorIsolation actorIsolation)
201+
: kind(Actor), actorIsolation(actorIsolation),
202+
isolatedValue(isolatedValue), actorInstance(actorInstance) {
203+
assert(actorInstance);
204+
assert(actorIsolation.getKind() == ActorIsolation::ActorInstance);
205+
}
206+
137207
SILIsolationInfo(Kind kind, SILValue isolatedValue)
138208
: kind(kind), actorIsolation(), isolatedValue(isolatedValue) {}
139209

@@ -180,7 +250,7 @@ class SILIsolationInfo {
180250

181251
/// Return the specific SILValue for the actor that our isolated value is
182252
/// isolated to if one exists.
183-
SILValue getActorInstance() const {
253+
ActorInstance getActorInstance() const {
184254
assert(kind == Actor);
185255
return actorInstance;
186256
}
@@ -237,6 +307,19 @@ class SILIsolationInfo {
237307
ActorIsolation::forActorInstanceSelf(typeDecl)};
238308
}
239309

310+
static SILIsolationInfo getActorInstanceIsolated(SILValue isolatedValue,
311+
ActorInstance actorInstance,
312+
NominalTypeDecl *typeDecl) {
313+
assert(actorInstance);
314+
if (!typeDecl->isAnyActor()) {
315+
assert(!swift::getActorIsolation(typeDecl).isGlobalActor() &&
316+
"Should have called getGlobalActorIsolated");
317+
return {};
318+
}
319+
return {isolatedValue, actorInstance,
320+
ActorIsolation::forActorInstanceSelf(typeDecl)};
321+
}
322+
240323
/// A special actor instance isolated for partial apply cases where we do not
241324
/// close over the isolated parameter and thus do not know the actual actor
242325
/// instance that we are going to use.

lib/SILOptimizer/Utils/PartitionUtils.cpp

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,20 @@ SILIsolationInfo SILIsolationInfo::get(SILArgument *arg) {
439439
return SILIsolationInfo::getDisconnected();
440440
}
441441
}
442+
443+
if (auto functionIsolation = fArg->getFunction()->getActorIsolation()) {
444+
if (declRef.getDecl()) {
445+
if (auto *accessor =
446+
dyn_cast_or_null<AccessorDecl>(declRef.getFuncDecl())) {
447+
if (accessor->isInitAccessor()) {
448+
assert(functionIsolation.isActorInstanceIsolated());
449+
return SILIsolationInfo::getActorInstanceIsolated(
450+
fArg, ActorInstance::getForActorAccessorInit(),
451+
functionIsolation.getActor());
452+
}
453+
}
454+
}
455+
}
442456
}
443457

444458
// Otherwise, if we do not have an isolated argument and are not in an
@@ -463,10 +477,20 @@ void SILIsolationInfo::print(llvm::raw_ostream &os) const {
463477
os << "disconnected";
464478
return;
465479
case Actor:
466-
if (SILValue instance = getActorInstance()) {
467-
if (auto name = VariableNameInferrer::inferName(instance)) {
468-
os << "'" << *name << "'-isolated\n";
469-
os << "instance: " << *instance;
480+
if (ActorInstance instance = getActorInstance()) {
481+
switch (instance.getKind()) {
482+
case ActorInstance::Kind::Value: {
483+
SILValue value = instance.getValue();
484+
if (auto name = VariableNameInferrer::inferName(value)) {
485+
os << "'" << *name << "'-isolated\n";
486+
os << "instance: " << *value;
487+
return;
488+
}
489+
break;
490+
}
491+
case ActorInstance::Kind::ActorAccessorInit:
492+
os << "'self'-isolated\n";
493+
os << "instance: actor accessor init\n";
470494
return;
471495
}
472496
}
@@ -519,9 +543,9 @@ bool SILIsolationInfo::hasSameIsolation(const SILIsolationInfo &other) const {
519543
return true;
520544
case Task:
521545
return getIsolatedValue() == other.getIsolatedValue();
522-
case Actor:
523-
auto actor1 = getActorInstance();
524-
auto actor2 = other.getActorInstance();
546+
case Actor: {
547+
ActorInstance actor1 = getActorInstance();
548+
ActorInstance actor2 = other.getActorInstance();
525549

526550
// If either are non-null, and the actor instance doesn't match, return
527551
// false.
@@ -532,6 +556,7 @@ bool SILIsolationInfo::hasSameIsolation(const SILIsolationInfo &other) const {
532556
auto rhsIsolation = other.getActorIsolation();
533557
return lhsIsolation == rhsIsolation;
534558
}
559+
}
535560
}
536561

537562
bool SILIsolationInfo::isEqual(const SILIsolationInfo &other) const {
@@ -579,9 +604,18 @@ void SILIsolationInfo::printForDiagnostics(llvm::raw_ostream &os) const {
579604
os << "disconnected";
580605
return;
581606
case Actor:
582-
if (SILValue instance = getActorInstance()) {
583-
if (auto name = VariableNameInferrer::inferName(instance)) {
584-
os << "'" << *name << "'-isolated";
607+
if (auto instance = getActorInstance()) {
608+
switch (instance.getKind()) {
609+
case ActorInstance::Kind::Value: {
610+
SILValue value = instance.getValue();
611+
if (auto name = VariableNameInferrer::inferName(value)) {
612+
os << "'" << *name << "'-isolated";
613+
return;
614+
}
615+
break;
616+
}
617+
case ActorInstance::Kind::ActorAccessorInit:
618+
os << "'self'-isolated";
585619
return;
586620
}
587621
}

test/Concurrency/flow_isolation.swift

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -812,26 +812,6 @@ func testActorWithInitAccessorInit() {
812812
print(a) // Ok (nonisolated)
813813
}
814814
}
815-
816-
class NonSendableKlass {
817-
init(_ x: NonSendableKlass? = nil) {
818-
819-
}
820-
}
821-
822-
@available(SwiftStdlib 5.1, *)
823-
actor NonSendableInit {
824-
var first: NonSendableKlass
825-
var second: NonSendableKlass? = nil {
826-
@storageRestrictions(initializes: first)
827-
init(initialValue) {
828-
first = initialValue!
829-
}
830-
831-
get { fatalError() }
832-
set { fatalError() }
833-
}
834-
}
835815
}
836816

837817
@available(SwiftStdlib 5.1, *)

0 commit comments

Comments
 (0)