Skip to content

Commit 7061bc7

Browse files
committed
[Distributed] ban typed throws in distributed funcs
They don't yield a correct error type as we didn't implement it, so rather allow it and risk crashes, ban it until we get the time to implement it. The real solution is to adjust typed throws error inference to do an union of the thrown error of the func and the type thrown by the distributed actor system remote call -- which today always would be (E | Error) -> Error... We could add a new associated type to DAS and then we could make it more proper... resolves rdar://136467528
1 parent ab8b1cd commit 7061bc7

File tree

3 files changed

+46
-0
lines changed

3 files changed

+46
-0
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5649,6 +5649,9 @@ ERROR(distributed_actor_func_unsupported_specifier, none,
56495649
ERROR(distributed_actor_func_variadic, none,
56505650
"cannot declare variadic argument %0 in %kind1",
56515651
(DeclName, const ValueDecl *))
5652+
ERROR(distributed_actor_func_typed_throws, none,
5653+
"cannot declare distributed function function with typed throws",
5654+
())
56525655
NOTE(actor_mutable_state,none,
56535656
"mutation of this %0 is only permitted within the actor",
56545657
(DescriptiveDeclKind))

lib/Sema/TypeCheckDistributed.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,19 @@ bool CheckDistributedFunctionRequest::evaluate(
618618
return true;
619619
}
620620

621+
// TODO: rdar://136467591 Currently typed throws were not implemented for distributed methods
622+
if (func->hasThrows()) {
623+
if (auto thrownError = func->getEffectiveThrownErrorType()) {
624+
// Basically we only support throwing `any Error` out of a distributed
625+
// function because then the effective error thrown by thunk calls naturally
626+
// is correct and the same `any Error`
627+
if (thrownError.has_value() &&
628+
!(*thrownError)->isEqual(C.getErrorExistentialType())) {
629+
func->diagnose(diag::distributed_actor_func_typed_throws);
630+
}
631+
}
632+
}
633+
621634
return false;
622635
}
623636

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// RUN: %target-swift-frontend -typecheck -verify -target %target-swift-5.7-abi-triple -I %t 2>&1 %s
2+
3+
// UNSUPPORTED: back_deploy_concurrency
4+
// REQUIRES: concurrency
5+
// REQUIRES: distributed
6+
7+
import Distributed
8+
9+
typealias DefaultDistributedActorSystem = LocalTestingDistributedActorSystem
10+
11+
distributed actor Foo {
12+
distributed func alwaysThrows() throws(FooError) { // expected-error{{cannot declare distributed function function with typed throws}}
13+
throw FooError()
14+
}
15+
}
16+
17+
struct FooError: Codable, Error { }
18+
struct RemoteInvocationError: Codable, Error { }
19+
20+
func test(foo: Foo) async throws {
21+
do {
22+
try await foo.alwaysThrows() // actually, this is throws(Error) because network errors etc
23+
fatalError("Should not reach here")
24+
// FIXME: the following warning is showing why we had to ban typed throws;
25+
// the error type must instead be (FooError | Error (from the distributed thunk))
26+
// rdar://136467591
27+
} catch let error as RemoteInvocationError { // expected-warning{{cast from 'FooError' to unrelated type 'RemoteInvocationError' always fails}}
28+
print("error = \(error)")
29+
}
30+
}

0 commit comments

Comments
 (0)