Skip to content

Commit 52df427

Browse files
authored
Merge pull request #40061 from DougGregor/existential-isolated-parameter-fix
2 parents b4f6511 + 04cd00e commit 52df427

File tree

3 files changed

+47
-10
lines changed

3 files changed

+47
-10
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,6 +1025,7 @@ namespace {
10251025
ASTContext &ctx;
10261026
SmallVector<const DeclContext *, 4> contextStack;
10271027
SmallVector<ApplyExpr*, 4> applyStack;
1028+
SmallVector<std::pair<OpaqueValueExpr *, Expr *>, 4> opaqueValues;
10281029

10291030
/// Keeps track of the capture context of variables that have been
10301031
/// explicitly captured in closures.
@@ -1244,6 +1245,13 @@ namespace {
12441245
}
12451246

12461247
std::pair<bool, Expr *> walkToExprPre(Expr *expr) override {
1248+
if (auto *openExistential = dyn_cast<OpenExistentialExpr>(expr)) {
1249+
opaqueValues.push_back({
1250+
openExistential->getOpaqueValue(),
1251+
openExistential->getExistentialValue()});
1252+
return { true, expr };
1253+
}
1254+
12471255
if (auto *closure = dyn_cast<AbstractClosureExpr>(expr)) {
12481256
closure->setActorIsolation(determineClosureIsolation(closure));
12491257
contextStack.push_back(closure);
@@ -1363,6 +1371,12 @@ namespace {
13631371
}
13641372

13651373
Expr *walkToExprPost(Expr *expr) override {
1374+
if (auto *openExistential = dyn_cast<OpenExistentialExpr>(expr)) {
1375+
assert(opaqueValues.back().first == openExistential->getOpaqueValue());
1376+
opaqueValues.pop_back();
1377+
return expr;
1378+
}
1379+
13661380
if (auto *closure = dyn_cast<AbstractClosureExpr>(expr)) {
13671381
assert(contextStack.back() == closure);
13681382
contextStack.pop_back();
@@ -1398,7 +1412,7 @@ namespace {
13981412
private:
13991413
/// Find the directly-referenced parameter or capture of a parameter for
14001414
/// for the given expression.
1401-
static VarDecl *getReferencedParamOrCapture(Expr *expr) {
1415+
VarDecl *getReferencedParamOrCapture(Expr *expr) {
14021416
// Look through identity expressions and implicit conversions.
14031417
Expr *prior;
14041418
do {
@@ -1408,6 +1422,16 @@ namespace {
14081422

14091423
if (auto conversion = dyn_cast<ImplicitConversionExpr>(expr))
14101424
expr = conversion->getSubExpr();
1425+
1426+
// Map opaque values.
1427+
if (auto opaqueValue = dyn_cast<OpaqueValueExpr>(expr)) {
1428+
for (const auto &known : opaqueValues) {
1429+
if (known.first == opaqueValue) {
1430+
expr = known.second;
1431+
break;
1432+
}
1433+
}
1434+
}
14111435
} while (prior != expr);
14121436

14131437
// 'super' references always act on a 'self' variable.
@@ -1550,7 +1574,7 @@ namespace {
15501574
}
15511575

15521576
/// If the expression is a reference to `self`, the `self` declaration.
1553-
static VarDecl *getReferencedSelf(Expr *expr) {
1577+
VarDecl *getReferencedSelf(Expr *expr) {
15541578
if (auto selfVar = getReferencedParamOrCapture(expr))
15551579
if (selfVar->isSelfParameter() || selfVar->isSelfParamCapture())
15561580
return selfVar;
@@ -1593,8 +1617,8 @@ namespace {
15931617
// detect if it is a distributed actor, to provide better isolation notes
15941618

15951619
auto isDistributedActor = false;
1596-
if (auto dc = dyn_cast<ClassDecl>(decl->getDeclContext()))
1597-
isDistributedActor = dc->isDistributedActor();
1620+
if (auto nominal = decl->getDeclContext()->getSelfNominalTypeDecl())
1621+
isDistributedActor = nominal->isDistributedActor();
15981622

15991623
// FIXME: Make this diagnostic more sensitive to the isolation context of
16001624
// the declaration.
@@ -2538,8 +2562,8 @@ namespace {
25382562
case ActorIsolationRestriction::Unsafe:
25392563
// This case is hit when passing actor state inout to functions in some
25402564
// cases. The error is emitted by diagnoseInOutArg.
2541-
auto classDecl = dyn_cast<ClassDecl>(member->getDeclContext());
2542-
if (classDecl && classDecl->isDistributedActor()) {
2565+
auto nominal = member->getDeclContext()->getSelfNominalTypeDecl();
2566+
if (nominal && nominal->isDistributedActor()) {
25432567
auto funcDecl = dyn_cast<AbstractFunctionDecl>(member);
25442568
if (funcDecl && !funcDecl->isStatic()) {
25452569
member->diagnose(diag::distributed_actor_isolated_method);

test/Concurrency/isolated_parameters.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,16 @@ func testIsolatedClosureInference(a: A) {
131131
a2.f()
132132
}
133133
}
134+
135+
// "isolated" existential parameters.
136+
protocol P2: Actor {
137+
func m()
138+
}
139+
140+
@available(SwiftStdlib 5.1, *)
141+
func testExistentialIsolated(a: isolated P2, b: P2) async {
142+
a.m()
143+
await b.m()
144+
b.m() // expected-error{{expression is 'async' but is not marked with 'await'}}
145+
// expected-note@-1{{calls to instance method 'm()' from outside of its actor context are implicitly asynchronous}}
146+
}

test/Distributed/distributed_protocol_isolation.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ protocol DistProtocol: DistributedActor {
1818
// FIXME(distributed): avoid issuing these warnings, these originate from the call on the DistProtocol where we marked this func as dist isolated,
1919
func local() -> String
2020
// (the note appears a few times, because we misuse the call many times)
21-
// expected-note@-2{{calls to instance method 'local()' from outside of its actor context are implicitly asynchronous}}
22-
// expected-note@-3{{calls to instance method 'local()' from outside of its actor context are implicitly asynchronous}}
23-
// expected-note@-4{{calls to instance method 'local()' from outside of its actor context are implicitly asynchronous}}
21+
// expected-note@-2{{distributed actor-isolated instance method 'local()' declared here}}
22+
// expected-note@-3{{distributed actor-isolated instance method 'local()' declared here}}
23+
// expected-note@-4{{distributed actor-isolated instance method 'local()' declared here}}
2424

2525
distributed func dist() -> String
2626
distributed func dist(string: String) -> String
@@ -202,4 +202,4 @@ extension TacoPreparation {
202202
// expected-error@-1{{'distributed' function can only be declared within 'distributed actor'}}
203203
}
204204

205-
distributed actor TacoWorker: DistributedTacoMaker {} // implemented in extensions
205+
distributed actor TacoWorker: DistributedTacoMaker {} // implemented in extensions

0 commit comments

Comments
 (0)