Skip to content

Commit 0914e58

Browse files
committed
[Distributed] Allow overloads with different types; mangling can handle it
1 parent 6810618 commit 0914e58

File tree

3 files changed

+108
-23
lines changed

3 files changed

+108
-23
lines changed

lib/Sema/TypeCheckDistributed.cpp

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -761,19 +761,34 @@ void TypeChecker::checkDistributedActor(SourceFile *SF, NominalTypeDecl *nominal
761761
auto candidates = nominal->lookupDirect(func->getName());
762762
if (candidates.size() > 1) {
763763
auto firstDecl = dyn_cast<AbstractFunctionDecl>(candidates.back());
764-
for (auto decl : candidates) {
765-
if (decl == firstDecl) {
766-
decl->diagnose(
767-
diag::distributed_func_cannot_overload_on_async_only,
768-
decl->getName());
769-
} else {
770-
decl->diagnose(
771-
diag::distributed_func_other_ambiguous_overload_here,
772-
decl->getName());
764+
for (auto candidate: candidates) {
765+
if (auto candidateFunc = dyn_cast<AbstractFunctionDecl>(candidate)) {
766+
assert(candidateFunc->getParameters()->size() ==
767+
firstDecl->getParameters()->size());
768+
bool allSame = true;
769+
for (size_t i = 0; i < candidateFunc->getParameters()->size(); ++i) {
770+
auto lhs = firstDecl->getParameters()->get(i);
771+
auto rhs = candidateFunc->getParameters()->get(i);
772+
if (!lhs->getInterfaceType()->isEqual(rhs->getInterfaceType())) {
773+
allSame = false;
774+
break;
775+
}
776+
}
777+
778+
if (candidate != firstDecl && // can't be ambiguous with itself
779+
allSame && // diagnose if ambiguous
780+
!diagnosedAmbiguity.contains(func->getName())) {
781+
candidate->diagnose(
782+
diag::distributed_func_cannot_overload_on_async_only,
783+
candidate->getName());
784+
diagnosedAmbiguity.insert(func->getName());
785+
} else if (diagnosedAmbiguity.contains(func->getName())) {
786+
candidate->diagnose(
787+
diag::distributed_func_other_ambiguous_overload_here,
788+
candidate->getName());
789+
}
773790
}
774791
}
775-
776-
diagnosedAmbiguity.insert(func->getName());
777792
}
778793
}
779794
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
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-build-swift -module-name main -Xfrontend -disable-availability-checking -j2 -parse-as-library -I %t %s %S/../Inputs/FakeDistributedActorSystems.swift -o %t/a.out
4+
// RUN: %target-codesign %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+
// rdar://76038845
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: OS=windows-msvc
17+
18+
import Distributed
19+
import FakeDistributedActorSystems
20+
21+
typealias DefaultDistributedActorSystem = FakeRoundtripActorSystem
22+
23+
distributed actor Greeter {
24+
distributed func callMe(_ name: String) -> String {
25+
return "\(name)"
26+
}
27+
distributed func callMe(_ number: Int) -> String {
28+
return "\(number)"
29+
}
30+
}
31+
32+
struct SomeError: Error, Sendable, Codable {}
33+
34+
func test() async throws {
35+
let system = DefaultDistributedActorSystem()
36+
37+
let local = Greeter(actorSystem: system)
38+
let ref = try Greeter.resolve(id: local.id, using: system)
39+
40+
do {
41+
let echo = try await ref.callMe("hello")
42+
precondition(echo == "hello")
43+
// CHECK: >> remoteCall: on:main.Greeter, target:main.Greeter.callMe(_:), invocation:FakeInvocationEncoder(genericSubs: [], arguments: ["hello"], returnType: Optional(Swift.String), errorType: nil), throwing:Swift.Never, returning:Swift.String
44+
45+
let echo2 = try await ref.callMe(42)
46+
precondition(echo2 == "42")
47+
// CHECK: >> remoteCall: on:main.Greeter, target:main.Greeter.callMe(_:), invocation:FakeInvocationEncoder(genericSubs: [], arguments: [42], returnType: Optional(Swift.String), errorType: nil), throwing:Swift.Never, returning:Swift.String
48+
49+
print("did not throw")
50+
// CHECK: did not throw
51+
} catch {
52+
print("error: \(error)")
53+
// CHECK-NOT: error:
54+
}
55+
}
56+
57+
@main struct Main {
58+
static func main() async {
59+
try! await test()
60+
}
61+
}

test/Distributed/distributed_func_overloads.swift

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,34 @@ distributed actor Overloader {
1616
func overloaded() {}
1717
func overloaded() async {}
1818

19-
distributed func overloadedDistA() {} // expected-note{{ambiguous distributed func 'overloadedDistA()' declared here}}
20-
distributed func overloadedDistA() async {} // expected-error{{ambiguous distributed func declaration 'overloadedDistA()', cannot overload distributed methods on effect only}}
19+
distributed func overloadedDistA() {} // expected-error{{ambiguous distributed func declaration 'overloadedDistA()', cannot overload distributed methods on effect only}}
20+
distributed func overloadedDistA() async {} // expected-note{{ambiguous distributed func 'overloadedDistA()' declared here}}
2121

22-
distributed func overloadedDistT() throws {} // expected-note{{ambiguous distributed func 'overloadedDistT()' declared here}}
23-
distributed func overloadedDistT() async throws {} // expected-error{{ambiguous distributed func declaration 'overloadedDistT()', cannot overload distributed methods on effect only}}
22+
distributed func overloadedDistT() throws {} // expected-error{{ambiguous distributed func declaration 'overloadedDistT()', cannot overload distributed methods on effect only}}
23+
distributed func overloadedDistT() async throws {} // expected-note{{ambiguous distributed func 'overloadedDistT()' declared here}}
2424

2525
// Throws overloads are not legal anyway, but let's check for them here too:
2626
distributed func overloadedDistThrows() {}
27-
// expected-note@-1{{ambiguous distributed func 'overloadedDistThrows()' declared here}}
28-
// expected-note@-2{{'overloadedDistThrows()' previously declared here}}
27+
// expected-note@-1{{'overloadedDistThrows()' previously declared here}}
28+
// expected-error@-2{{ambiguous distributed func declaration 'overloadedDistThrows()', cannot overload distributed methods on effect only}}
2929
distributed func overloadedDistThrows() throws {}
30-
// expected-error@-1{{ambiguous distributed func declaration 'overloadedDistThrows()', cannot overload distributed methods on effect only}}
31-
// expected-error@-2{{invalid redeclaration of 'overloadedDistThrows()'}}
30+
// expected-error@-1{{invalid redeclaration of 'overloadedDistThrows()'}}
31+
// expected-note@-2{{ambiguous distributed func 'overloadedDistThrows()' declared here}}
3232

3333
distributed func overloadedDistAsync() async {}
34-
// expected-note@-1{{ambiguous distributed func 'overloadedDistAsync()' declared here}}
35-
// expected-note@-2{{'overloadedDistAsync()' previously declared here}}
34+
// expected-note@-1{{'overloadedDistAsync()' previously declared here}}
35+
// expected-error@-2{{ambiguous distributed func declaration 'overloadedDistAsync()', cannot overload distributed methods on effect only}}
3636
distributed func overloadedDistAsync() async throws {}
37-
// expected-error@-1{{ambiguous distributed func declaration 'overloadedDistAsync()', cannot overload distributed methods on effect only}}
38-
// expected-error@-2{{invalid redeclaration of 'overloadedDistAsync()'}}
37+
// expected-error@-1{{invalid redeclaration of 'overloadedDistAsync()'}}
38+
// expected-note@-2{{ambiguous distributed func 'overloadedDistAsync()' declared here}}
39+
40+
// overloads differing by parameter type are allowed,
41+
// since the mangled identifier includes full type information:
42+
distributed func overloadedDistParams(param: String) async {}
43+
distributed func overloadedDistParams(param: Int) async {}
44+
45+
distributed func overloadedDistParams() async {} // also ok
46+
47+
distributed func overloadedDistParams<A: Sendable & Codable>(param: A) async {}
3948
}
4049

0 commit comments

Comments
 (0)