Skip to content

Commit 88c0a9e

Browse files
authored
Merge pull request #42578 from ktoso/pick-prevent-multiple-id-synthesis
🍒[5.7][Distributed] Guard ID synthesis from happening multiple times
2 parents 786fbf8 + 4740bdd commit 88c0a9e

File tree

5 files changed

+107
-0
lines changed

5 files changed

+107
-0
lines changed

include/swift/AST/DistributedDecl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ class DeclContext;
3131
class FuncDecl;
3232
class NominalTypeDecl;
3333

34+
/// Obtain a distributed actor's well-known property by name.
35+
VarDecl* lookupDistributedActorProperty(NominalTypeDecl *decl, DeclName name);
36+
3437
/// Determine the concrete type of 'ActorSystem' as seen from the member.
3538
/// E.g. when in a protocol, and trying to determine what the actor system was
3639
/// constrained to.

lib/AST/DistributedDecl.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,45 @@
6161

6262
using namespace swift;
6363

64+
/******************************************************************************/
65+
/********************** Distributed Actor Properties **************************/
66+
/******************************************************************************/
67+
68+
VarDecl* swift::lookupDistributedActorProperty(NominalTypeDecl *decl, DeclName name) {
69+
assert(decl && "decl was null");
70+
auto &C = decl->getASTContext();
71+
72+
auto clazz = dyn_cast<ClassDecl>(decl);
73+
if (!clazz)
74+
return nullptr;
75+
76+
auto refs = decl->lookupDirect(name);
77+
if (refs.size() != 1)
78+
return nullptr;
79+
80+
auto var = dyn_cast<VarDecl>(refs.front());
81+
if (!var)
82+
return nullptr;
83+
84+
Type expectedType = Type();
85+
if (name == C.Id_id) {
86+
expectedType = getDistributedActorIDType(decl);
87+
} else if (name == C.Id_actorSystem) {
88+
expectedType = getDistributedActorSystemType(decl);
89+
} else {
90+
llvm_unreachable("Unexpected distributed actor property lookup!");
91+
}
92+
if (!expectedType)
93+
return nullptr;
94+
95+
if (!var->getInterfaceType()->isEqual(expectedType))
96+
return nullptr;
97+
98+
assert(var->isSynthesized() && "Expected compiler synthesized property");
99+
return var;
100+
}
101+
102+
64103
/******************************************************************************/
65104
/************** Distributed Actor System Associated Types *********************/
66105
/******************************************************************************/

lib/Sema/CodeSynthesisDistributedActor.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,13 @@ VarDecl *GetDistributedActorIDPropertyRequest::evaluate(
773773
if (!classDecl)
774774
return nullptr;
775775

776+
// We may enter this request multiple times, e.g. in multi-file projects,
777+
// so in order to avoid synthesizing a property many times, first perform
778+
// a lookup and return if it already exists.
779+
if (auto existingProp = lookupDistributedActorProperty(classDecl, C.Id_id)) {
780+
return existingProp;
781+
}
782+
776783
return addImplicitDistributedActorIDProperty(classDecl);
777784
}
778785

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift open source project
4+
//
5+
// Copyright (c) 2021 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
import Distributed
16+
17+
distributed actor Echo /* in the mirror */{
18+
typealias ActorSystem = LocalTestingDistributedActorSystem
19+
20+
distributed func echo(_ input: String) -> String {
21+
return "echo: \(input)"
22+
}
23+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend-emit-module -emit-module-path %t/FakeDistributedActorSystems.swiftmodule -module-name FakeDistributedActorSystems -disable-availability-checking %S/../Inputs/FakeDistributedActorSystems.swift
3+
// RUN: %target-swift-frontend-emit-module -emit-module-path %t/EchoActorModule.swiftmodule -module-name EchoActorModule -disable-availability-checking %S/../Inputs/EchoActor.swift
4+
// RUN: %target-build-swift -module-name main -Xfrontend -enable-experimental-distributed -Xfrontend -disable-availability-checking -j2 -parse-as-library -I %t %s %S/../Inputs/FakeDistributedActorSystems.swift %S/../Inputs/EchoActor.swift -o %t/a.out
5+
// RUN: %target-run %t/a.out | %FileCheck %s --color
6+
7+
// REQUIRES: executable_test
8+
// REQUIRES: concurrency
9+
// REQUIRES: distributed
10+
11+
12+
// UNSUPPORTED: use_os_stdlib
13+
// UNSUPPORTED: back_deployment_runtime
14+
15+
// FIXME(distributed): Distributed actors currently have some issues on windows, isRemote always returns false. rdar://82593574
16+
// UNSUPPORTED: windows
17+
18+
import Distributed
19+
import EchoActorModule
20+
import FakeDistributedActorSystems
21+
22+
func test() async {
23+
let system = LocalTestingDistributedActorSystem()
24+
25+
let echo = Echo(actorSystem: system)
26+
let reply = try! await echo.echo("in the mirror")
27+
// CHECK: reply: echo: in the mirror
28+
print("reply: \(reply)")
29+
}
30+
31+
@main struct Main {
32+
static func main() async {
33+
await test()
34+
}
35+
}

0 commit comments

Comments
 (0)